Move docs to material-mkdocs

This commit is contained in:
Michael Shamoon 2022-11-29 12:49:23 -08:00
parent a96f79f6a3
commit 605f885e19
58 changed files with 5198 additions and 5895 deletions

View File

@ -42,35 +42,13 @@ jobs:
name: Checkout
uses: actions/checkout@v3
-
name: Install pipenv
run: |
pipx install pipenv==2022.10.12
-
name: Set up Python
uses: actions/setup-python@v4
with:
python-version: 3.9
cache: "pipenv"
cache-dependency-path: 'Pipfile.lock'
-
name: Install dependencies
run: |
pipenv sync --dev
-
name: List installed Python dependencies
run: |
pipenv run pip list
-
name: Make documentation
run: |
cd docs/
pipenv run make html
-
name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: documentation
path: docs/_build/html/
name: Deploy docs
uses: mhausenblas/mkdocs-deploy-gh-pages@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CUSTOM_DOMAIN: paperless-ngx.com
CONFIG_FILE: mkdocs.yml
EXTRA_PACKAGES: build-base
tests-backend:
name: "Tests (${{ matrix.python-version }})"

View File

@ -1,16 +0,0 @@
# .readthedocs.yml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Build documentation in the docs/ directory with Sphinx
sphinx:
configuration: docs/conf.py
# Optionally set the version of Python and requirements required to build your docs
python:
version: "3.8"
install:
- requirements: docs/requirements.txt

View File

@ -71,10 +71,9 @@ pytest-django = "*"
pytest-env = "*"
pytest-sugar = "*"
pytest-xdist = "*"
sphinx = "~=5.3"
sphinx_rtd_theme = "*"
tox = "*"
black = "*"
pre-commit = "*"
sphinx-autobuild = "*"
myst-parser = "*"
mkdocs-material = "*"

129
Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "9fefc737155e789ced61b41750b4273c7780ac7801c50cf36dc5925be3b85783"
"sha256": "0242e3e296e09b30fb69e0d7a2f2e8feb4c6a23d3c7ec99500f2883a032a8c84"
},
"pipfile-spec": 6,
"requires": {},
@ -99,6 +99,7 @@
"sha256:f04e857b59d9d1ccc39ce2da1021d196e47234873820cbeaad210724b1ee28ac",
"sha256:fadbfe37f74051d024037f223b8e001611eac868b5c5b06144ef4d8b799862f2"
],
"index": "pypi",
"markers": "python_version < '3.9'",
"version": "==0.2.1"
},
@ -218,7 +219,7 @@
"sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845",
"sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"
],
"markers": "python_full_version >= '3.6.0'",
"markers": "python_version >= '3.6'",
"version": "==2.1.1"
},
"click": {
@ -234,7 +235,7 @@
"sha256:a0713dc7a1de3f06bc0df5a9567ad19ead2d3d5689b434768a6145bff77c0667",
"sha256:f184f0d851d96b6d29297354ed981b7dd71df7ff500d82fa6d11f0856bee8035"
],
"markers": "python_full_version >= '3.6.2' and python_full_version < '4.0.0'",
"markers": "python_version < '4' and python_full_version >= '3.6.2'",
"version": "==0.3.0"
},
"click-plugins": {
@ -1624,7 +1625,7 @@
"sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa",
"sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"
],
"markers": "python_version >= '3.7'",
"markers": "python_version < '3.10'",
"version": "==4.4.0"
},
"tzdata": {
@ -2054,7 +2055,7 @@
"sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845",
"sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"
],
"markers": "python_full_version >= '3.6.0'",
"markers": "python_version >= '3.6'",
"version": "==2.1.1"
},
"click": {
@ -2074,6 +2075,9 @@
"version": "==0.4.6"
},
"coverage": {
"extras": [
"toml"
],
"hashes": [
"sha256:027018943386e7b942fa832372ebc120155fd970837489896099f5cfa2890f79",
"sha256:11b990d520ea75e7ee8dcab5bc908072aaada194a794db9f6d7d5cfd19661e5a",
@ -2198,6 +2202,13 @@
"index": "pypi",
"version": "==3.8.0"
},
"ghp-import": {
"hashes": [
"sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619",
"sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"
],
"version": "==2.1.0"
},
"identify": {
"hashes": [
"sha256:48b7925fe122720088aeb7a6c34f17b27e706b72c61070f27fe3789094233440",
@ -2222,6 +2233,14 @@
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.4.1"
},
"importlib-metadata": {
"hashes": [
"sha256:d5059f9f1e8e41f80e9c56c2ee58811450c31984dfa625329ffd7c0dad88a73b",
"sha256:d84d17e21670ec07990e1044a99efe8d615d860fd176fc29ef5c306068fda313"
],
"markers": "python_version < '3.10'",
"version": "==5.1.0"
},
"iniconfig": {
"hashes": [
"sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3",
@ -2243,6 +2262,14 @@
],
"version": "==2.6.3"
},
"markdown": {
"hashes": [
"sha256:cbb516f16218e643d8e0a95b309f77eb118cb138d39a4f27851e6a63581db874",
"sha256:f5da449a6e1c989a4cea2631aa8ee67caa5a2ef855d551c88f9e309f4634c621"
],
"markers": "python_version >= '3.6'",
"version": "==3.3.7"
},
"markdown-it-py": {
"hashes": [
"sha256:93de681e5c021a432c63147656fe21790bc01231e0cd2da73626f1aa3ac0fe27",
@ -2313,6 +2340,38 @@
"markers": "python_version >= '3.7'",
"version": "==0.1.2"
},
"mergedeep": {
"hashes": [
"sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8",
"sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307"
],
"markers": "python_version >= '3.6'",
"version": "==1.3.4"
},
"mkdocs": {
"hashes": [
"sha256:8947af423a6d0facf41ea1195b8e1e8c85ad94ac95ae307fe11232e0424b11c5",
"sha256:c8856a832c1e56702577023cd64cc5f84948280c1c0fcc6af4cd39006ea6aa8c"
],
"markers": "python_version >= '3.7'",
"version": "==1.4.2"
},
"mkdocs-material": {
"hashes": [
"sha256:b0ea0513fd8cab323e8a825d6692ea07fa83e917bb5db042e523afecc7064ab7",
"sha256:c907b4b052240a5778074a30a78f31a1f8ff82d7012356dc26898b97559f082e"
],
"index": "pypi",
"version": "==8.5.11"
},
"mkdocs-material-extensions": {
"hashes": [
"sha256:9c003da71e2cc2493d910237448c672e00cefc800d3d6ae93d2fc69979e3bd93",
"sha256:e41d9f38e4798b6617ad98ca8f7f1157b1e4385ac1459ca1e4ea219b556df945"
],
"markers": "python_version >= '3.7'",
"version": "==1.1.1"
},
"mypy-extensions": {
"hashes": [
"sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d",
@ -2400,6 +2459,14 @@
"markers": "python_version >= '3.6'",
"version": "==2.13.0"
},
"pymdown-extensions": {
"hashes": [
"sha256:0f8fb7b74a37a61cc34e90b2c91865458b713ec774894ffad64353a5fce85cfc",
"sha256:ac698c15265680db5eb13cd4342abfcde2079ac01e5486028f47a1b41547b859"
],
"markers": "python_version >= '3.7'",
"version": "==9.9"
},
"pyparsing": {
"hashes": [
"sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb",
@ -2516,6 +2583,14 @@
],
"version": "==6.0"
},
"pyyaml-env-tag": {
"hashes": [
"sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb",
"sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069"
],
"markers": "python_version >= '3.6'",
"version": "==0.1"
},
"requests": {
"hashes": [
"sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983",
@ -2552,7 +2627,6 @@
"sha256:060ca5c9f7ba57a08a1219e547b269fadf125ae25b06b9fa7f66768efb652d6d",
"sha256:51026de0a9ff9fc13c05d74913ad66047e104f56a129ff73e174eb5c3ee794b5"
],
"index": "pypi",
"version": "==5.3.0"
},
"sphinx-autobuild": {
@ -2640,7 +2714,7 @@
"sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc",
"sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"
],
"markers": "python_full_version < '3.11.0a7'",
"markers": "python_version < '3.11' and python_version >= '3.7'",
"version": "==2.0.1"
},
"tornado": {
@ -2673,7 +2747,7 @@
"sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa",
"sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"
],
"markers": "python_version >= '3.7'",
"markers": "python_version < '3.10'",
"version": "==4.4.0"
},
"urllib3": {
@ -2691,6 +2765,45 @@
],
"markers": "python_version >= '3.6'",
"version": "==20.16.6"
},
"watchdog": {
"hashes": [
"sha256:083171652584e1b8829581f965b9b7723ca5f9a2cd7e20271edf264cfd7c1412",
"sha256:117ffc6ec261639a0209a3252546b12800670d4bf5f84fbd355957a0595fe654",
"sha256:186f6c55abc5e03872ae14c2f294a153ec7292f807af99f57611acc8caa75306",
"sha256:195fc70c6e41237362ba720e9aaf394f8178bfc7fa68207f112d108edef1af33",
"sha256:226b3c6c468ce72051a4c15a4cc2ef317c32590d82ba0b330403cafd98a62cfd",
"sha256:247dcf1df956daa24828bfea5a138d0e7a7c98b1a47cf1fa5b0c3c16241fcbb7",
"sha256:255bb5758f7e89b1a13c05a5bceccec2219f8995a3a4c4d6968fe1de6a3b2892",
"sha256:43ce20ebb36a51f21fa376f76d1d4692452b2527ccd601950d69ed36b9e21609",
"sha256:4f4e1c4aa54fb86316a62a87b3378c025e228178d55481d30d857c6c438897d6",
"sha256:5952135968519e2447a01875a6f5fc8c03190b24d14ee52b0f4b1682259520b1",
"sha256:64a27aed691408a6abd83394b38503e8176f69031ca25d64131d8d640a307591",
"sha256:6b17d302850c8d412784d9246cfe8d7e3af6bcd45f958abb2d08a6f8bedf695d",
"sha256:70af927aa1613ded6a68089a9262a009fbdf819f46d09c1a908d4b36e1ba2b2d",
"sha256:7a833211f49143c3d336729b0020ffd1274078e94b0ae42e22f596999f50279c",
"sha256:8250546a98388cbc00c3ee3cc5cf96799b5a595270dfcfa855491a64b86ef8c3",
"sha256:97f9752208f5154e9e7b76acc8c4f5a58801b338de2af14e7e181ee3b28a5d39",
"sha256:9f05a5f7c12452f6a27203f76779ae3f46fa30f1dd833037ea8cbc2887c60213",
"sha256:a735a990a1095f75ca4f36ea2ef2752c99e6ee997c46b0de507ba40a09bf7330",
"sha256:ad576a565260d8f99d97f2e64b0f97a48228317095908568a9d5c786c829d428",
"sha256:b530ae007a5f5d50b7fbba96634c7ee21abec70dc3e7f0233339c81943848dc1",
"sha256:bfc4d351e6348d6ec51df007432e6fe80adb53fd41183716017026af03427846",
"sha256:d3dda00aca282b26194bdd0adec21e4c21e916956d972369359ba63ade616153",
"sha256:d9820fe47c20c13e3c9dd544d3706a2a26c02b2b43c993b62fcd8011bcc0adb3",
"sha256:ed80a1628cee19f5cfc6bb74e173f1b4189eb532e705e2a13e3250312a62e0c9",
"sha256:ee3e38a6cc050a8830089f79cbec8a3878ec2fe5160cdb2dc8ccb6def8552658"
],
"index": "pypi",
"version": "==2.1.9"
},
"zipp": {
"hashes": [
"sha256:4fcb6f278987a6605757302a6e40e896257570d11c51628968ccb2a47e80c6c1",
"sha256:7a7262fd930bd3e36c50b9a64897aec3fafff3dfdeec9623ae22b40e93f99bb8"
],
"markers": "python_version < '3.9'",
"version": "==3.10.0"
}
}
}

View File

@ -1,181 +0,0 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# User-friendly check for sphinx-build
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
endif
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " livehtml to preview changes with live reload in your browser"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " xml to make Docutils-native XML files"
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
livehtml:
sphinx-autobuild "./" "$(BUILDDIR)" $(O)
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/RIPEAtlasToolsMagellan.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/RIPEAtlasToolsMagellan.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/RIPEAtlasToolsMagellan"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/RIPEAtlasToolsMagellan"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
latexpdfja:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through platex and dvipdfmx..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
xml:
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
@echo
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."

View File

@ -1,597 +0,0 @@
/* Variables */
:root {
--color-text-body: #5c5962;
--color-text-body-light: #fcfcfc;
--color-text-anchor: #7253ed;
--color-text-alt: rgba(0, 0, 0, 0.3);
--color-text-title: #27262b;
--color-text-code-inline: #e74c3c;
--color-text-code-nt: #062873;
--color-text-selection: #b19eff;
--color-bg-body: #fcfcfc;
--color-bg-body-alt: #f3f6f6;
--color-bg-side-nav: #f5f6fa;
--color-bg-side-nav-hover: #ebedf5;
--color-bg-code-block: var(--color-bg-side-nav);
--color-border: #eeebee;
--color-btn-neutral-bg: #f3f6f6;
--color-btn-neutral-bg-hover: #e5ebeb;
--color-success-title: #1abc9c;
--color-success-body: #dbfaf4;
--color-warning-title: #f0b37e;
--color-warning-body: #ffedcc;
--color-danger-title: #f29f97;
--color-danger-body: #fdf3f2;
--color-info-title: #6ab0de;
--color-info-body: #e7f2fa;
}
.dark-mode {
--color-text-body: #abb2bf;
--color-text-body-light: #9499a2;
--color-text-alt: rgba(0255, 255, 255, 0.5);
--color-text-title: var(--color-text-anchor);
--color-text-code-inline: #abb2bf;
--color-text-code-nt: #2063f3;
--color-text-selection: #030303;
--color-bg-body: #1d1d20 !important;
--color-bg-body-alt: #131315;
--color-bg-side-nav: #18181a;
--color-bg-side-nav-hover: #101216;
--color-bg-code-block: #101216;
--color-border: #47494f;
--color-btn-neutral-bg: #242529;
--color-btn-neutral-bg-hover: #101216;
--color-success-title: #02120f;
--color-success-body: #041b17;
--color-warning-title: #1b0e03;
--color-warning-body: #371d06;
--color-danger-title: #120902;
--color-danger-body: #1b0503;
--color-info-title: #020608;
--color-info-body: #06141e;
}
* {
transition: background-color 0.3s ease, border-color 0.3s ease;
}
/* Typography */
body {
font-family: system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
font-size: inherit;
line-height: 1.4;
color: var(--color-text-body);
}
.rst-content p {
word-break: break-word;
}
h1, h2, h3, h4, h5, h6 {
font-family: inherit;
}
.rst-content .toctree-wrapper>p.caption, .rst-content h1, .rst-content h2, .rst-content h3, .rst-content h4, .rst-content h5, .rst-content h6 {
padding-top: .5em;
}
p, .main-content-wrap, .rst-content .section ul, .rst-content .toctree-wrapper ul, .rst-content section ul, .wy-plain-list-disc, article ul {
line-height: 1.6;
}
pre, .code, .rst-content .linenodiv pre, .rst-content div[class^=highlight] pre, .rst-content pre.literal-block {
font-family: "SFMono-Regular", Menlo,Consolas, Monospace;
font-size: 0.75em;
line-height: 1.8;
}
.wy-menu-vertical li.toctree-l3,.wy-menu-vertical li.toctree-l4 {
font-size: 1rem
}
.rst-versions {
font-family: inherit;
line-height: 1;
}
footer, footer p {
font-size: .8rem;
}
footer .rst-footer-buttons {
font-size: 1rem;
}
@media (max-width: 400px) {
/* break code lines on mobile */
pre, code {
word-break: break-word;
}
}
/* Layout */
.wy-side-nav-search, .wy-menu-vertical {
width: auto;
}
.wy-nav-side {
z-index: 0;
display: flex;
flex-wrap: wrap;
background-color: var(--color-bg-side-nav);
}
.wy-side-scroll {
width: 100%;
overflow-y: auto;
}
@media (min-width: 66.5rem) {
.wy-side-scroll {
width:264px
}
}
@media (min-width: 50rem) {
.wy-nav-side {
flex-wrap: nowrap;
position: fixed;
width: 248px;
height: 100%;
flex-direction: column;
border-right: 1px solid var(--color-border);
align-items:flex-end
}
}
@media (min-width: 66.5rem) {
.wy-nav-side {
width: calc((100% - 1064px) / 2 + 264px);
min-width:264px
}
}
@media (min-width: 50rem) {
.wy-nav-content-wrap {
position: relative;
max-width: 800px;
margin-left:248px
}
}
@media (min-width: 66.5rem) {
.wy-nav-content-wrap {
margin-left:calc((100% - 1064px) / 2 + 264px)
}
}
/* Colors */
body.wy-body-for-nav,
.wy-nav-content {
background: var(--color-bg-body);
}
.wy-nav-side {
border-right: 1px solid var(--color-border);
}
.wy-side-nav-search, .wy-nav-top {
background: var(--color-bg-side-nav);
border-bottom: 1px solid var(--color-border);
}
.wy-nav-content-wrap {
background: inherit;
}
.wy-side-nav-search > a, .wy-nav-top a, .wy-nav-top i {
color: var(--color-text-title);
}
.wy-side-nav-search > a:hover, .wy-nav-top a:hover {
background: transparent;
}
.wy-side-nav-search > div.version {
color: var(--color-text-alt)
}
.wy-side-nav-search > div[role="search"] {
border-top: 1px solid var(--color-border);
}
.wy-menu-vertical li.toctree-l2.current>a, .wy-menu-vertical li.toctree-l2.current li.toctree-l3>a,
.wy-menu-vertical li.toctree-l3.current>a, .wy-menu-vertical li.toctree-l3.current li.toctree-l4>a {
background: var(--color-bg-side-nav);
}
.rst-content .highlighted {
background: #eedd85;
box-shadow: 0 0 0 2px #eedd85;
font-weight: 600;
}
.wy-side-nav-search input[type=text],
html.writer-html5 .rst-content table.docutils th {
color: var(--color-text-body);
}
.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td,
.wy-table-backed,
.wy-table-odd td,
.wy-table-striped tr:nth-child(2n-1) td {
background-color: var(--color-bg-body-alt);
}
.rst-content table.docutils,
.wy-table-bordered-all,
html.writer-html5 .rst-content table.docutils th,
.rst-content table.docutils td,
.wy-table-bordered-all td,
hr {
border-color: var(--color-border) !important;
}
::selection {
background: var(--color-text-selection);
}
/* Ridiculous rules are taken from sphinx_rtd */
.rst-content .admonition-title,
.wy-alert-title {
color: var(--color-text-body-light);
}
.rst-content .hint,
.rst-content .important,
.rst-content .tip,
.rst-content .wy-alert-success,
.wy-alert.wy-alert-success {
background: var(--color-success-body);
}
.rst-content .hint .admonition-title,
.rst-content .hint .wy-alert-title,
.rst-content .important .admonition-title,
.rst-content .important .wy-alert-title,
.rst-content .tip .admonition-title,
.rst-content .tip .wy-alert-title,
.rst-content .wy-alert-success .admonition-title,
.rst-content .wy-alert-success .wy-alert-title,
.wy-alert.wy-alert-success .rst-content .admonition-title,
.wy-alert.wy-alert-success .wy-alert-title {
background-color: var(--color-success-title);
}
.rst-content .admonition-todo,
.rst-content .attention,
.rst-content .caution,
.rst-content .warning,
.rst-content .wy-alert-warning,
.wy-alert.wy-alert-warning {
background: var(--color-warning-body);
}
.rst-content .admonition-todo .admonition-title,
.rst-content .admonition-todo .wy-alert-title,
.rst-content .attention .admonition-title,
.rst-content .attention .wy-alert-title,
.rst-content .caution .admonition-title,
.rst-content .caution .wy-alert-title,
.rst-content .warning .admonition-title,
.rst-content .warning .wy-alert-title,
.rst-content .wy-alert-warning .admonition-title,
.rst-content .wy-alert-warning .wy-alert-title,
.rst-content .wy-alert.wy-alert-warning .admonition-title,
.wy-alert.wy-alert-warning .rst-content .admonition-title,
.wy-alert.wy-alert-warning .wy-alert-title {
background: var(--color-warning-title);
}
.rst-content .danger,
.rst-content .error,
.rst-content .wy-alert-danger,
.wy-alert.wy-alert-danger {
background: var(--color-danger-body);
}
.rst-content .danger .admonition-title,
.rst-content .danger .wy-alert-title,
.rst-content .error .admonition-title,
.rst-content .error .wy-alert-title,
.rst-content .wy-alert-danger .admonition-title,
.rst-content .wy-alert-danger .wy-alert-title,
.wy-alert.wy-alert-danger .rst-content .admonition-title,
.wy-alert.wy-alert-danger .wy-alert-title {
background: var(--color-danger-title);
}
.rst-content .note,
.rst-content .seealso,
.rst-content .wy-alert-info,
.wy-alert.wy-alert-info {
background: var(--color-info-body);
}
.rst-content .note .admonition-title,
.rst-content .note .wy-alert-title,
.rst-content .seealso .admonition-title,
.rst-content .seealso .wy-alert-title,
.rst-content .wy-alert-info .admonition-title,
.rst-content .wy-alert-info .wy-alert-title,
.wy-alert.wy-alert-info .rst-content .admonition-title,
.wy-alert.wy-alert-info .wy-alert-title {
background: var(--color-info-title);
}
/* Links */
a, a:visited,
.wy-menu-vertical a,
a.icon.icon-home,
.wy-menu-vertical li.toctree-l1.current > a.current {
color: var(--color-text-anchor);
text-decoration: none;
}
a:hover, .wy-breadcrumbs-aside a {
color: var(--color-text-anchor); /* reset */
}
.rst-versions a, .rst-versions .rst-current-version {
color: #var(--color-text-anchor);
}
.wy-nav-content a.reference, .wy-nav-content a:not([class]) {
background-image: linear-gradient(var(--color-border) 0%, var(--color-border) 100%);
background-repeat: repeat-x;
background-position: 0 100%;
background-size: 1px 1px;
}
.wy-nav-content a.reference:hover, .wy-nav-content a:not([class]):hover {
background-image: linear-gradient(rgba(114,83,237,0.45) 0%, rgba(114,83,237,0.45) 100%);
background-size: 1px 1px;
}
.wy-menu-vertical a:hover,
.wy-menu-vertical li.current a:hover,
.wy-menu-vertical a:active {
background: var(--color-bg-side-nav-hover) !important;
color: var(--color-text-body);
}
.wy-menu-vertical li.toctree-l1.current>a,
.wy-menu-vertical li.current>a,
.wy-menu-vertical li.on a {
background-color: var(--color-bg-side-nav-hover);
border: none;
font-weight: normal;
}
.wy-menu-vertical li.current {
background-color: inherit;
}
.wy-menu-vertical li.current a {
border-right: none;
}
.wy-menu-vertical li.toctree-l2 a,
.wy-menu-vertical li.toctree-l3 a,
.wy-menu-vertical li.toctree-l4 a,
.wy-menu-vertical li.toctree-l5 a,
.wy-menu-vertical li.toctree-l6 a,
.wy-menu-vertical li.toctree-l7 a,
.wy-menu-vertical li.toctree-l8 a,
.wy-menu-vertical li.toctree-l9 a,
.wy-menu-vertical li.toctree-l10 a {
color: var(--color-text-body);
}
a.image-reference, a.image-reference:hover {
background: none !important;
}
a.image-reference img {
cursor: zoom-in;
}
/* Code blocks */
.rst-content code, .rst-content tt, code {
padding: 0.25em;
font-weight: 400;
background-color: var(--color-bg-code-block);
border: 1px solid var(--color-border);
border-radius: 4px;
}
.rst-content div[class^=highlight], .rst-content pre.literal-block {
padding: 0.7rem;
margin-top: 0;
margin-bottom: 0.75rem;
overflow-x: auto;
background-color: var(--color-bg-side-nav);
border-color: var(--color-border);
border-radius: 4px;
box-shadow: none;
}
.rst-content .admonition-title,
.rst-content div.admonition,
.wy-alert-title {
padding: 10px 12px;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.highlight .go {
color: inherit;
}
.highlight .nt {
color: var(--color-text-code-nt);
}
.rst-content code.literal,
.rst-content tt.literal,
html.writer-html5 .rst-content dl.footnote code {
border-color: var(--color-border);
background-color: var(--color-border);
color: var(--color-text-code-inline)
}
/* Search */
.wy-side-nav-search input[type=text] {
border: none;
border-radius: 0;
background-color: transparent;
font-family: inherit;
font-size: .85rem;
box-shadow: none;
padding: .7rem 1rem .7rem 2.8rem;
margin: 0;
}
#rtd-search-form {
position: relative;
}
#rtd-search-form:before {
font: normal normal normal 14px/1 FontAwesome;
font-size: inherit;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
content: "\f002";
color: var(--color-text-alt);
position: absolute;
left: 1.5rem;
top: .7rem;
}
/* Side nav */
.wy-side-nav-search {
padding: 1rem 0 0 0;
}
.wy-menu-vertical li a button.toctree-expand {
float: right;
margin-right: -1.5em;
padding: 0 .5em;
}
.wy-menu-vertical a,
.wy-menu-vertical li.current>a,
.wy-menu-vertical li.current li>a {
padding-right: 1.5em !important;
}
.wy-menu-vertical li.current li>a.current {
font-weight: 600;
}
/* Misc spacing */
.rst-content .admonition-title, .wy-alert-title {
padding: 10px 12px;
}
/* Buttons */
.btn {
display: inline-block;
box-sizing: border-box;
padding: 0.3em 1em;
margin: 0;
font-family: inherit;
font-size: inherit;
font-weight: 500;
line-height: 1.5;
color: #var(--color-text-anchor);
text-decoration: none;
vertical-align: baseline;
background-color: #f7f7f7;
border-width: 0;
border-radius: 4px;
box-shadow: 0 1px 2px rgba(0,0,0,0.12),0 3px 10px rgba(0,0,0,0.08);
appearance: none;
}
.btn:active {
padding: 0.3em 1em;
}
.rst-content .btn:focus {
outline: 1px solid #ccc;
}
.rst-content .btn-neutral, .rst-content .btn span.fa {
color: var(--color-text-body) !important;
}
.btn-neutral {
background-color: var(--color-btn-neutral-bg) !important;
color: var(--color-btn-neutral-text) !important;
border: 1px solid var(--color-btn-neutral-bg);
}
.btn:hover, .btn-neutral:hover {
background-color: var(--color-btn-neutral-bg-hover) !important;
}
/* Icon overrides */
.wy-side-nav-search a.icon-home:before {
display: none;
}
.fa-minus-square-o:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before {
content: "\f106"; /* fa-angle-up */
}
.fa-plus-square-o:before, .wy-menu-vertical li button.toctree-expand:before {
content: "\f107"; /* fa-angle-down */
}
/* Misc */
.wy-nav-top {
line-height: 36px;
}
.wy-nav-top > i {
font-size: 24px;
padding: 8px 0 0 2px;
color:#var(--color-text-anchor);
}
.rst-content table.docutils td,
.rst-content table.docutils th,
.rst-content table.field-list td,
.rst-content table.field-list th,
.wy-table td,
.wy-table th {
padding: 8px 14px;
}
.dark-mode-toggle {
position: absolute;
top: 14px;
right: 12px;
height: 20px;
width: 24px;
z-index: 10;
border: none;
background-color: transparent;
color: inherit;
opacity: 0.7;
}
.wy-nav-content-wrap {
z-index: 20;
}

View File

@ -1,47 +0,0 @@
let toggleButton
let icon
function load() {
'use strict'
toggleButton = document.createElement('button')
toggleButton.setAttribute('title', 'Toggle dark mode')
toggleButton.classList.add('dark-mode-toggle')
icon = document.createElement('i')
icon.classList.add('fa', darkModeState ? 'fa-sun-o' : 'fa-moon-o')
toggleButton.appendChild(icon)
document.body.prepend(toggleButton)
// Listen for changes in the OS settings
// addListener is used because older versions of Safari don't support addEventListener
// prefersDarkQuery set in <head>
if (prefersDarkQuery) {
prefersDarkQuery.addListener(function (evt) {
toggleDarkMode(evt.matches)
})
}
// Initial setting depending on the prefers-color-mode or localstorage
// darkModeState should be set in the document <head> to prevent flash
if (darkModeState == undefined) darkModeState = false
toggleDarkMode(darkModeState)
// Toggles the "dark-mode" class on click and sets localStorage state
toggleButton.addEventListener('click', () => {
darkModeState = !darkModeState
toggleDarkMode(darkModeState)
localStorage.setItem('dark-mode', darkModeState)
})
}
function toggleDarkMode(state) {
document.documentElement.classList.toggle('dark-mode', state)
document.documentElement.classList.toggle('light-mode', !state)
icon.classList.remove('fa-sun-o')
icon.classList.remove('fa-moon-o')
icon.classList.add(state ? 'fa-sun-o' : 'fa-moon-o')
darkModeState = state
}
document.addEventListener('DOMContentLoaded', load)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

View File

@ -1,13 +0,0 @@
{% extends "!layout.html" %}
{% block extrahead %}
<script>
// MediaQueryList object
const prefersDarkQuery = window.matchMedia("(prefers-color-scheme: dark)");
const lsDark = localStorage.getItem("dark-mode");
let darkModeState = lsDark !== null ? lsDark == "true" : prefersDarkQuery.matches;
document.documentElement.classList.toggle("dark-mode", darkModeState);
document.documentElement.classList.toggle("light-mode", !darkModeState);
</script>
{{ super() }}
{% endblock %}

503
docs/administration.md Normal file
View File

@ -0,0 +1,503 @@
# Administration
## Making backups {#backup}
Multiple options exist for making backups of your paperless instance,
depending on how you installed paperless.
Before making backups, make sure that paperless is not running.
Options available to any installation of paperless:
- Use the [document exporter](/administration#exporter). The document exporter exports all your documents,
thumbnails and metadata to a specific folder. You may import your
documents into a fresh instance of paperless again or store your
documents in another DMS with this export.
- The document exporter is also able to update an already existing
export. Therefore, incremental backups with `rsync` are entirely
possible.
!!! caution
You cannot import the export generated with one version of paperless in
a different version of paperless. The export contains an exact image of
the database, and migrations may change the database layout.
Options available to docker installations:
- Backup the docker volumes. These usually reside within
`/var/lib/docker/volumes` on the host and you need to be root in
order to access them.
Paperless uses 4 volumes:
- `paperless_media`: This is where your documents are stored.
- `paperless_data`: This is where auxillary data is stored. This
folder also contains the SQLite database, if you use it.
- `paperless_pgdata`: Exists only if you use PostgreSQL and
contains the database.
- `paperless_dbdata`: Exists only if you use MariaDB and contains
the database.
Options available to bare-metal and non-docker installations:
- Backup the entire paperless folder. This ensures that if your
paperless instance crashes at some point or your disk fails, you can
simply copy the folder back into place and it works.
When using PostgreSQL or MariaDB, you'll also have to backup the
database.
### Restoring {#migrating-restoring}
## Updating Paperless {#updating}
### Docker Route
If a new release of paperless-ngx is available, upgrading depends on how
you installed paperless-ngx in the first place. The releases are
available at the [release
page](https://github.com/paperless-ngx/paperless-ngx/releases).
First of all, ensure that paperless is stopped.
```shell-session
$ cd /path/to/paperless
$ docker-compose down
```
After that, [make a backup](#backup).
A. If you pull the image from the docker hub, all you need to do is:
``` shell-session
$ docker-compose pull
$ docker-compose up
```
The docker-compose files refer to the `latest` version, which is
always the latest stable release.
B. If you built the image yourself, do the following:
``` shell-session
$ git pull
$ docker-compose build
$ docker-compose up
```
Running `docker-compose up` will also apply any new database migrations.
If you see everything working, press CTRL+C once to gracefully stop
paperless. Then you can start paperless-ngx with `-d` to have it run in
the background.
!!! note
In version 0.9.14, the update process was changed. In 0.9.13 and
earlier, the docker-compose files specified exact versions and pull
won't automatically update to newer versions. In order to enable
updates as described above, either get the new `docker-compose.yml`
file from
[here](https://github.com/paperless-ngx/paperless-ngx/tree/master/docker/compose)
or edit the `docker-compose.yml` file, find the line that says
```
image: ghcr.io/paperless-ngx/paperless-ngx:0.9.x
```
and replace the version with `latest`:
```
image: ghcr.io/paperless-ngx/paperless-ngx:latest
```
!!! note
In version 1.7.1 and onwards, the Docker image can now be pinned to a
release series. This is often combined with automatic updaters such as
Watchtower to allow safer unattended upgrading to new bugfix releases
only. It is still recommended to always review release notes before
upgrading. To pin your install to a release series, edit the
`docker-compose.yml` find the line that says
```
image: ghcr.io/paperless-ngx/paperless-ngx:latest
```
and replace the version with the series you want to track, for
example:
```
image: ghcr.io/paperless-ngx/paperless-ngx:1.7
```
### Bare Metal Route
After grabbing the new release and unpacking the contents, do the
following:
1. Update dependencies. New paperless version may require additional
dependencies. The dependencies required are listed in the section
about
[bare metal installations](/setup#bare_metal).
2. Update python requirements. Keep in mind to activate your virtual
environment before that, if you use one.
```shell-session
$ pip install -r requirements.txt
```
3. Migrate the database.
```shell-session
$ cd src
$ python3 manage.py migrate
```
This might not actually do anything. Not every new paperless version
comes with new database migrations.
## Downgrading Paperless
Downgrades are possible. However, some updates also contain database
migrations (these change the layout of the database and may move data).
In order to move back from a version that applied database migrations,
you'll have to revert the database migration _before_ downgrading, and
then downgrade paperless.
This table lists the compatible versions for each database migration
number.
| Migration number | Version range |
| ---------------- | --------------- |
| 1011 | 1.0.0 |
| 1012 | 1.1.0 - 1.2.1 |
| 1014 | 1.3.0 - 1.3.1 |
| 1016 | 1.3.2 - current |
Execute the following management command to migrate your database:
```shell-session
$ python3 manage.py migrate documents <migration number>
```
!!! note
Some migrations cannot be undone. The command will issue errors if that
happens.
## Management utilities {#management-commands}
Paperless comes with some management commands that perform various
maintenance tasks on your paperless instance. You can invoke these
commands in the following way:
With docker-compose, while paperless is running:
```shell-session
$ cd /path/to/paperless
$ docker-compose exec webserver <command> <arguments>
```
With docker, while paperless is running:
```shell-session
$ docker exec -it <container-name> <command> <arguments>
```
Bare metal:
```shell-session
$ cd /path/to/paperless/src
$ python3 manage.py <command> <arguments>
```
All commands have built-in help, which can be accessed by executing them
with the argument `--help`.
### Document exporter {#exporter}
The document exporter exports all your data from paperless into a folder
for backup or migration to another DMS.
If you use the document exporter within a cronjob to backup your data
you might use the `-T` flag behind exec to suppress "The input device
is not a TTY" errors. For example:
`docker-compose exec -T webserver document_exporter ../export`
```
document_exporter target [-c] [-f] [-d]
optional arguments:
-c, --compare-checksums
-f, --use-filename-format
-d, --delete
```
`target` is a folder to which the data gets written. This includes
documents, thumbnails and a `manifest.json` file. The manifest contains
all metadata from the database (correspondents, tags, etc).
When you use the provided docker compose script, specify `../export` as
the target. This path inside the container is automatically mounted on
your host on the folder `export`.
If the target directory already exists and contains files, paperless
will assume that the contents of the export directory are a previous
export and will attempt to update the previous export. Paperless will
only export changed and added files. Paperless determines whether a file
has changed by inspecting the file attributes "date/time modified" and
"size". If that does not work out for you, specify
`--compare-checksums` and paperless will attempt to compare file
checksums instead. This is slower.
Paperless will not remove any existing files in the export directory. If
you want paperless to also remove files that do not belong to the
current export such as files from deleted documents, specify `--delete`.
Be careful when pointing paperless to a directory that already contains
other files.
The filenames generated by this command follow the format
`[date created] [correspondent] [title].[extension]`. If you want
paperless to use `PAPERLESS_FILENAME_FORMAT` for exported filenames
instead, specify `--use-filename-format`.
### Document importer {#importer}
The document importer takes the export produced by the [Document
exporter](#document-exporter) and imports it into paperless.
The importer works just like the exporter. You point it at a directory,
and the script does the rest of the work:
```
document_importer source
```
When you use the provided docker compose script, put the export inside
the `export` folder in your paperless source directory. Specify
`../export` as the `source`.
!!! note
Importing from a previous version of Paperless may work, but for best
results it is suggested to match the versions.
### Document retagger {#retagger}
Say you've imported a few hundred documents and now want to introduce a
tag or set up a new correspondent, and apply its matching to all of the
currently-imported docs. This problem is common enough that there are
tools for it.
```
document_retagger [-h] [-c] [-T] [-t] [-i] [--use-first] [-f]
optional arguments:
-c, --correspondent
-T, --tags
-t, --document_type
-s, --storage_path
-i, --inbox-only
--use-first
-f, --overwrite
```
Run this after changing or adding matching rules. It'll loop over all
of the documents in your database and attempt to match documents
according to the new rules.
Specify any combination of `-c`, `-T`, `-t` and `-s` to have the
retagger perform matching of the specified metadata type. If you don't
specify any of these options, the document retagger won't do anything.
Specify `-i` to have the document retagger work on documents tagged with
inbox tags only. This is useful when you don't want to mess with your
already processed documents.
When multiple document types or correspondents match a single document,
the retagger won't assign these to the document. Specify `--use-first`
to override this behavior and just use the first correspondent or type
it finds. This option does not apply to tags, since any amount of tags
can be applied to a document.
Finally, `-f` specifies that you wish to overwrite already assigned
correspondents, types and/or tags. The default behavior is to not assign
correspondents and types to documents that have this data already
assigned. `-f` works differently for tags: By default, only additional
tags get added to documents, no tags will be removed. With `-f`, tags
that don't match a document anymore get removed as well.
### Managing the Automatic matching algorithm
The _Auto_ matching algorithm requires a trained neural network to work.
This network needs to be updated whenever somethings in your data
changes. The docker image takes care of that automatically with the task
scheduler. You can manually renew the classifier by invoking the
following management command:
```
document_create_classifier
```
This command takes no arguments.
### Managing the document search index {#index}
The document search index is responsible for delivering search results
for the website. The document index is automatically updated whenever
documents get added to, changed, or removed from paperless. However, if
the search yields non-existing documents or won't find anything, you
may need to recreate the index manually.
```
document_index {reindex,optimize}
```
Specify `reindex` to have the index created from scratch. This may take
some time.
Specify `optimize` to optimize the index. This updates certain aspects
of the index and usually makes queries faster and also ensures that the
autocompletion works properly. This command is regularly invoked by the
task scheduler.
### Managing filenames {#renamer}
If you use paperless' feature to
[assign custom filenames to your documents](/advanced_usage#file_name_handling), you can use this command to move all your files after
changing the naming scheme.
!!! warning
Since this command moves your documents, it is advised to do a backup
beforehand. The renaming logic is robust and will never overwrite or
delete a file, but you can't ever be careful enough.
```
document_renamer
```
The command takes no arguments and processes all your documents at once.
Learn how to use
`Management Utilities<utilities-management-commands>`{.interpreted-text
role="ref"}.
### Sanity checker {#sanity-checker}
Paperless has a built-in sanity checker that inspects your document
collection for issues.
The issues detected by the sanity checker are as follows:
- Missing original files.
- Missing archive files.
- Inaccessible original files due to improper permissions.
- Inaccessible archive files due to improper permissions.
- Corrupted original documents by comparing their checksum against
what is stored in the database.
- Corrupted archive documents by comparing their checksum against what
is stored in the database.
- Missing thumbnails.
- Inaccessible thumbnails due to improper permissions.
- Documents without any content (warning).
- Orphaned files in the media directory (warning). These are files
that are not referenced by any document im paperless.
```
document_sanity_checker
```
The command takes no arguments. Depending on the size of your document
archive, this may take some time.
### Fetching e-mail
Paperless automatically fetches your e-mail every 10 minutes by default.
If you want to invoke the email consumer manually, call the following
management command:
```
mail_fetcher
```
The command takes no arguments and processes all your mail accounts and
rules.
!!! note
As of October 2022 Microsoft no longer supports IMAP authentication
for Exchange servers, thus Exchange is no longer supported until a
solution is implemented in the Python IMAP library used by Paperless.
See
[learn.microsoft.com](https://learn.microsoft.com/en-us/exchange/clients-and-mobile-in-exchange-online/deprecation-of-basic-authentication-exchange-online)
### Creating archived documents {#archiver}
Paperless stores archived PDF/A documents alongside your original
documents. These archived documents will also contain selectable text
for image-only originals. These documents are derived from the
originals, which are always stored unmodified. If coming from an earlier
version of paperless, your documents won't have archived versions.
This command creates PDF/A documents for your documents.
```
document_archiver --overwrite --document <id>
```
This command will only attempt to create archived documents when no
archived document exists yet, unless `--overwrite` is specified. If
`--document <id>` is specified, the archiver will only process that
document.
!!! note
This command essentially performs OCR on all your documents again,
according to your settings. If you run this with
`PAPERLESS_OCR_MODE=redo`, it will potentially run for a very long time.
You can cancel the command at any time, since this command will skip
already archived versions the next time it is run.
!!! note
Some documents will cause errors and cannot be converted into PDF/A
documents, such as encrypted PDF documents. The archiver will skip over
these documents each time it sees them.
### Managing encryption {#encyption}
Documents can be stored in Paperless using GnuPG encryption.
!!! warning
Encryption is deprecated since paperless-ngx 0.9 and doesn't really
provide any additional security, since you have to store the passphrase
in a configuration file on the same system as the encrypted documents
for paperless to work. Furthermore, the entire text content of the
documents is stored plain in the database, even if your documents are
encrypted. Filenames are not encrypted as well.
Also, the web server provides transparent access to your encrypted
documents.
Consider running paperless on an encrypted filesystem instead, which
will then at least provide security against physical hardware theft.
#### Enabling encryption
Enabling encryption is no longer supported.
#### Disabling encryption
Basic usage to disable encryption of your document store:
(Note: If `PAPERLESS_PASSPHRASE` isn't set already, you need to specify
it here)
```
decrypt_documents [--passphrase SECR3TP4SSPHRA$E]
```

View File

@ -1,531 +0,0 @@
**************
Administration
**************
.. _administration-backup:
Making backups
##############
Multiple options exist for making backups of your paperless instance,
depending on how you installed paperless.
Before making backups, make sure that paperless is not running.
Options available to any installation of paperless:
* Use the :ref:`document exporter <utilities-exporter>`.
The document exporter exports all your documents, thumbnails and
metadata to a specific folder. You may import your documents into a
fresh instance of paperless again or store your documents in another
DMS with this export.
* The document exporter is also able to update an already existing export.
Therefore, incremental backups with ``rsync`` are entirely possible.
.. caution::
You cannot import the export generated with one version of paperless in a
different version of paperless. The export contains an exact image of the
database, and migrations may change the database layout.
Options available to docker installations:
* Backup the docker volumes. These usually reside within
``/var/lib/docker/volumes`` on the host and you need to be root in order
to access them.
Paperless uses 4 volumes:
* ``paperless_media``: This is where your documents are stored.
* ``paperless_data``: This is where auxillary data is stored. This
folder also contains the SQLite database, if you use it.
* ``paperless_pgdata``: Exists only if you use PostgreSQL and contains
the database.
* ``paperless_dbdata``: Exists only if you use MariaDB and contains
the database.
Options available to bare-metal and non-docker installations:
* Backup the entire paperless folder. This ensures that if your paperless instance
crashes at some point or your disk fails, you can simply copy the folder back
into place and it works.
When using PostgreSQL or MariaDB, you'll also have to backup the database.
.. _migrating-restoring:
Restoring
=========
.. _administration-updating:
Updating Paperless
##################
Docker Route
============
If a new release of paperless-ngx is available, upgrading depends on how you
installed paperless-ngx in the first place. The releases are available at the
`release page <https://github.com/paperless-ngx/paperless-ngx/releases>`_.
First of all, ensure that paperless is stopped.
.. code:: shell-session
$ cd /path/to/paperless
$ docker-compose down
After that, :ref:`make a backup <administration-backup>`.
A. If you pull the image from the docker hub, all you need to do is:
.. code:: shell-session
$ docker-compose pull
$ docker-compose up
The docker-compose files refer to the ``latest`` version, which is always the latest
stable release.
B. If you built the image yourself, do the following:
.. code:: shell-session
$ git pull
$ docker-compose build
$ docker-compose up
Running ``docker-compose up`` will also apply any new database migrations.
If you see everything working, press CTRL+C once to gracefully stop paperless.
Then you can start paperless-ngx with ``-d`` to have it run in the background.
.. note::
In version 0.9.14, the update process was changed. In 0.9.13 and earlier, the
docker-compose files specified exact versions and pull won't automatically
update to newer versions. In order to enable updates as described above, either
get the new ``docker-compose.yml`` file from `here <https://github.com/paperless-ngx/paperless-ngx/tree/master/docker/compose>`_
or edit the ``docker-compose.yml`` file, find the line that says
.. code::
image: ghcr.io/paperless-ngx/paperless-ngx:0.9.x
and replace the version with ``latest``:
.. code::
image: ghcr.io/paperless-ngx/paperless-ngx:latest
.. note::
In version 1.7.1 and onwards, the Docker image can now be pinned to a release series.
This is often combined with automatic updaters such as Watchtower to allow safer
unattended upgrading to new bugfix releases only. It is still recommended to always
review release notes before upgrading. To pin your install to a release series, edit
the ``docker-compose.yml`` find the line that says
.. code::
image: ghcr.io/paperless-ngx/paperless-ngx:latest
and replace the version with the series you want to track, for example:
.. code::
image: ghcr.io/paperless-ngx/paperless-ngx:1.7
Bare Metal Route
================
After grabbing the new release and unpacking the contents, do the following:
1. Update dependencies. New paperless version may require additional
dependencies. The dependencies required are listed in the section about
:ref:`bare metal installations <setup-bare_metal>`.
2. Update python requirements. Keep in mind to activate your virtual environment
before that, if you use one.
.. code:: shell-session
$ pip install -r requirements.txt
3. Migrate the database.
.. code:: shell-session
$ cd src
$ python3 manage.py migrate
This might not actually do anything. Not every new paperless version comes with new
database migrations.
Downgrading Paperless
#####################
Downgrades are possible. However, some updates also contain database migrations (these change the layout of the database and may move data).
In order to move back from a version that applied database migrations, you'll have to revert the database migration *before* downgrading,
and then downgrade paperless.
This table lists the compatible versions for each database migration number.
+------------------+-----------------+
| Migration number | Version range |
+------------------+-----------------+
| 1011 | 1.0.0 |
+------------------+-----------------+
| 1012 | 1.1.0 - 1.2.1 |
+------------------+-----------------+
| 1014 | 1.3.0 - 1.3.1 |
+------------------+-----------------+
| 1016 | 1.3.2 - current |
+------------------+-----------------+
Execute the following management command to migrate your database:
.. code:: shell-session
$ python3 manage.py migrate documents <migration number>
.. note::
Some migrations cannot be undone. The command will issue errors if that happens.
.. _utilities-management-commands:
Management utilities
####################
Paperless comes with some management commands that perform various maintenance
tasks on your paperless instance. You can invoke these commands in the following way:
With docker-compose, while paperless is running:
.. code:: shell-session
$ cd /path/to/paperless
$ docker-compose exec webserver <command> <arguments>
With docker, while paperless is running:
.. code:: shell-session
$ docker exec -it <container-name> <command> <arguments>
Bare metal:
.. code:: shell-session
$ cd /path/to/paperless/src
$ python3 manage.py <command> <arguments>
All commands have built-in help, which can be accessed by executing them with
the argument ``--help``.
.. _utilities-exporter:
Document exporter
=================
The document exporter exports all your data from paperless into a folder for
backup or migration to another DMS.
If you use the document exporter within a cronjob to backup your data you might use the ``-T`` flag behind exec to suppress "The input device is not a TTY" errors. For example: ``docker-compose exec -T webserver document_exporter ../export``
.. code::
document_exporter target [-c] [-f] [-d]
optional arguments:
-c, --compare-checksums
-f, --use-filename-format
-d, --delete
``target`` is a folder to which the data gets written. This includes documents,
thumbnails and a ``manifest.json`` file. The manifest contains all metadata from
the database (correspondents, tags, etc).
When you use the provided docker compose script, specify ``../export`` as the
target. This path inside the container is automatically mounted on your host on
the folder ``export``.
If the target directory already exists and contains files, paperless will assume
that the contents of the export directory are a previous export and will attempt
to update the previous export. Paperless will only export changed and added files.
Paperless determines whether a file has changed by inspecting the file attributes
"date/time modified" and "size". If that does not work out for you, specify
``--compare-checksums`` and paperless will attempt to compare file checksums instead.
This is slower.
Paperless will not remove any existing files in the export directory. If you want
paperless to also remove files that do not belong to the current export such as files
from deleted documents, specify ``--delete``. Be careful when pointing paperless to
a directory that already contains other files.
The filenames generated by this command follow the format
``[date created] [correspondent] [title].[extension]``.
If you want paperless to use ``PAPERLESS_FILENAME_FORMAT`` for exported filenames
instead, specify ``--use-filename-format``.
.. _utilities-importer:
Document importer
=================
The document importer takes the export produced by the `Document exporter`_ and
imports it into paperless.
The importer works just like the exporter. You point it at a directory, and
the script does the rest of the work:
.. code::
document_importer source
When you use the provided docker compose script, put the export inside the
``export`` folder in your paperless source directory. Specify ``../export``
as the ``source``.
.. note::
Importing from a previous version of Paperless may work, but for best results
it is suggested to match the versions.
.. _utilities-retagger:
Document retagger
=================
Say you've imported a few hundred documents and now want to introduce
a tag or set up a new correspondent, and apply its matching to all of
the currently-imported docs. This problem is common enough that
there are tools for it.
.. code::
document_retagger [-h] [-c] [-T] [-t] [-i] [--use-first] [-f]
optional arguments:
-c, --correspondent
-T, --tags
-t, --document_type
-s, --storage_path
-i, --inbox-only
--use-first
-f, --overwrite
Run this after changing or adding matching rules. It'll loop over all
of the documents in your database and attempt to match documents
according to the new rules.
Specify any combination of ``-c``, ``-T``, ``-t`` and ``-s`` to have the
retagger perform matching of the specified metadata type. If you don't
specify any of these options, the document retagger won't do anything.
Specify ``-i`` to have the document retagger work on documents tagged
with inbox tags only. This is useful when you don't want to mess with
your already processed documents.
When multiple document types or correspondents match a single document,
the retagger won't assign these to the document. Specify ``--use-first``
to override this behavior and just use the first correspondent or type
it finds. This option does not apply to tags, since any amount of tags
can be applied to a document.
Finally, ``-f`` specifies that you wish to overwrite already assigned
correspondents, types and/or tags. The default behavior is to not
assign correspondents and types to documents that have this data already
assigned. ``-f`` works differently for tags: By default, only additional tags get
added to documents, no tags will be removed. With ``-f``, tags that don't
match a document anymore get removed as well.
Managing the Automatic matching algorithm
=========================================
The *Auto* matching algorithm requires a trained neural network to work.
This network needs to be updated whenever somethings in your data
changes. The docker image takes care of that automatically with the task
scheduler. You can manually renew the classifier by invoking the following
management command:
.. code::
document_create_classifier
This command takes no arguments.
.. _`administration-index`:
Managing the document search index
==================================
The document search index is responsible for delivering search results for the
website. The document index is automatically updated whenever documents get
added to, changed, or removed from paperless. However, if the search yields
non-existing documents or won't find anything, you may need to recreate the
index manually.
.. code::
document_index {reindex,optimize}
Specify ``reindex`` to have the index created from scratch. This may take some
time.
Specify ``optimize`` to optimize the index. This updates certain aspects of
the index and usually makes queries faster and also ensures that the
autocompletion works properly. This command is regularly invoked by the task
scheduler.
.. _utilities-renamer:
Managing filenames
==================
If you use paperless' feature to
:ref:`assign custom filenames to your documents <advanced-file_name_handling>`,
you can use this command to move all your files after changing
the naming scheme.
.. warning::
Since this command moves your documents, it is advised to do
a backup beforehand. The renaming logic is robust and will never overwrite
or delete a file, but you can't ever be careful enough.
.. code::
document_renamer
The command takes no arguments and processes all your documents at once.
Learn how to use :ref:`Management Utilities<utilities-management-commands>`.
.. _utilities-sanity-checker:
Sanity checker
==============
Paperless has a built-in sanity checker that inspects your document collection for issues.
The issues detected by the sanity checker are as follows:
* Missing original files.
* Missing archive files.
* Inaccessible original files due to improper permissions.
* Inaccessible archive files due to improper permissions.
* Corrupted original documents by comparing their checksum against what is stored in the database.
* Corrupted archive documents by comparing their checksum against what is stored in the database.
* Missing thumbnails.
* Inaccessible thumbnails due to improper permissions.
* Documents without any content (warning).
* Orphaned files in the media directory (warning). These are files that are not referenced by any document im paperless.
.. code::
document_sanity_checker
The command takes no arguments. Depending on the size of your document archive, this may take some time.
Fetching e-mail
===============
Paperless automatically fetches your e-mail every 10 minutes by default. If
you want to invoke the email consumer manually, call the following management
command:
.. code::
mail_fetcher
The command takes no arguments and processes all your mail accounts and rules.
.. note::
As of October 2022 Microsoft no longer supports IMAP authentication for Exchange
servers, thus Exchange is no longer supported until a solution is implemented in
the Python IMAP library used by Paperless. See `learn.microsoft.com`_
.. _learn.microsoft.com: https://learn.microsoft.com/en-us/exchange/clients-and-mobile-in-exchange-online/deprecation-of-basic-authentication-exchange-online
.. _utilities-archiver:
Creating archived documents
===========================
Paperless stores archived PDF/A documents alongside your original documents.
These archived documents will also contain selectable text for image-only
originals.
These documents are derived from the originals, which are always stored
unmodified. If coming from an earlier version of paperless, your documents
won't have archived versions.
This command creates PDF/A documents for your documents.
.. code::
document_archiver --overwrite --document <id>
This command will only attempt to create archived documents when no archived
document exists yet, unless ``--overwrite`` is specified. If ``--document <id>``
is specified, the archiver will only process that document.
.. note::
This command essentially performs OCR on all your documents again,
according to your settings. If you run this with ``PAPERLESS_OCR_MODE=redo``,
it will potentially run for a very long time. You can cancel the command
at any time, since this command will skip already archived versions the next time
it is run.
.. note::
Some documents will cause errors and cannot be converted into PDF/A documents,
such as encrypted PDF documents. The archiver will skip over these documents
each time it sees them.
.. _utilities-encyption:
Managing encryption
===================
Documents can be stored in Paperless using GnuPG encryption.
.. danger::
Encryption is deprecated since paperless-ngx 0.9 and doesn't really provide any
additional security, since you have to store the passphrase in a configuration
file on the same system as the encrypted documents for paperless to work.
Furthermore, the entire text content of the documents is stored plain in the
database, even if your documents are encrypted. Filenames are not encrypted as
well.
Also, the web server provides transparent access to your encrypted documents.
Consider running paperless on an encrypted filesystem instead, which will then
at least provide security against physical hardware theft.
Enabling encryption
-------------------
Enabling encryption is no longer supported.
Disabling encryption
--------------------
Basic usage to disable encryption of your document store:
(Note: If ``PAPERLESS_PASSPHRASE`` isn't set already, you need to specify it here)
.. code::
decrypt_documents [--passphrase SECR3TP4SSPHRA$E]

464
docs/advanced_usage.md Normal file
View File

@ -0,0 +1,464 @@
# Advanced Topics
Paperless offers a couple features that automate certain tasks and make
your life easier.
## Matching tags, correspondents, document types, and storage paths {#matching}
Paperless will compare the matching algorithms defined by every tag,
correspondent, document type, and storage path in your database to see
if they apply to the text in a document. In other words, if you define a
tag called `Home Utility` that had a `match` property of `bc hydro` and
a `matching_algorithm` of `literal`, Paperless will automatically tag
your newly-consumed document with your `Home Utility` tag so long as the
text `bc hydro` appears in the body of the document somewhere.
The matching logic is quite powerful. It supports searching the text of
your document with different algorithms, and as such, some
experimentation may be necessary to get things right.
In order to have a tag, correspondent, document type, or storage path
assigned automatically to newly consumed documents, assign a match and
matching algorithm using the web interface. These settings define when
to assign tags, correspondents, document types, and storage paths to
documents.
The following algorithms are available:
- **Any:** Looks for any occurrence of any word provided in match in
the PDF. If you define the match as `Bank1 Bank2`, it will match
documents containing either of these terms.
- **All:** Requires that every word provided appears in the PDF,
albeit not in the order provided.
- **Literal:** Matches only if the match appears exactly as provided
(i.e. preserve ordering) in the PDF.
- **Regular expression:** Parses the match as a regular expression and
tries to find a match within the document.
- **Fuzzy match:** I don't know. Look at the source.
- **Auto:** Tries to automatically match new documents. This does not
require you to set a match. See the notes below.
When using the _any_ or _all_ matching algorithms, you can search for
terms that consist of multiple words by enclosing them in double quotes.
For example, defining a match text of `"Bank of America" BofA` using the
_any_ algorithm, will match documents that contain either "Bank of
America" or "BofA", but will not match documents containing "Bank of
South America".
Then just save your tag, correspondent, document type, or storage path
and run another document through the consumer. Once complete, you should
see the newly-created document, automatically tagged with the
appropriate data.
### Automatic matching {#automatic_matching}
Paperless-ngx comes with a new matching algorithm called _Auto_. This
matching algorithm tries to assign tags, correspondents, document types,
and storage paths to your documents based on how you have already
assigned these on existing documents. It uses a neural network under the
hood.
If, for example, all your bank statements of your account 123 at the
Bank of America are tagged with the tag "bofa*123" and the matching
algorithm of this tag is set to \_Auto*, this neural network will examine
your documents and automatically learn when to assign this tag.
Paperless tries to hide much of the involved complexity with this
approach. However, there are a couple caveats you need to keep in mind
when using this feature:
- Changes to your documents are not immediately reflected by the
matching algorithm. The neural network needs to be _trained_ on your
documents after changes. Paperless periodically (default: once each
hour) checks for changes and does this automatically for you.
- The Auto matching algorithm only takes documents into account which
are NOT placed in your inbox (i.e. have any inbox tags assigned to
them). This ensures that the neural network only learns from
documents which you have correctly tagged before.
- The matching algorithm can only work if there is a correlation
between the tag, correspondent, document type, or storage path and
the document itself. Your bank statements usually contain your bank
account number and the name of the bank, so this works reasonably
well, However, tags such as "TODO" cannot be automatically
assigned.
- The matching algorithm needs a reasonable number of documents to
identify when to assign tags, correspondents, storage paths, and
types. If one out of a thousand documents has the correspondent
"Very obscure web shop I bought something five years ago", it will
probably not assign this correspondent automatically if you buy
something from them again. The more documents, the better.
- Paperless also needs a reasonable amount of negative examples to
decide when not to assign a certain tag, correspondent, document
type, or storage path. This will usually be the case as you start
filling up paperless with documents. Example: If all your documents
are either from "Webshop" and "Bank", paperless will assign one
of these correspondents to ANY new document, if both are set to
automatic matching.
## Hooking into the consumption process
Sometimes you may want to do something arbitrary whenever a document is
consumed. Rather than try to predict what you may want to do, Paperless
lets you execute scripts of your own choosing just before or after a
document is consumed using a couple simple hooks.
Just write a script, put it somewhere that Paperless can read & execute,
and then put the path to that script in `paperless.conf` or
`docker-compose.env` with the variable name of either
`PAPERLESS_PRE_CONSUME_SCRIPT` or `PAPERLESS_POST_CONSUME_SCRIPT`.
!!! info
These scripts are executed in a **blocking** process, which means that
if a script takes a long time to run, it can significantly slow down
your document consumption flow. If you want things to run
asynchronously, you'll have to fork the process in your script and
exit.
### Pre-consumption script
Executed after the consumer sees a new document in the consumption
folder, but before any processing of the document is performed. This
script can access the following relevant environment variables set:
- `DOCUMENT_SOURCE_PATH`
A simple but common example for this would be creating a simple script
like this:
`/usr/local/bin/ocr-pdf`
```bash
#!/usr/bin/env bash
pdf2pdfocr.py -i ${DOCUMENT_SOURCE_PATH}
```
`/etc/paperless.conf`
```bash
...
PAPERLESS_PRE_CONSUME_SCRIPT="/usr/local/bin/ocr-pdf"
...
```
This will pass the path to the document about to be consumed to
`/usr/local/bin/ocr-pdf`, which will in turn call
[pdf2pdfocr.py](https://github.com/LeoFCardoso/pdf2pdfocr) on your
document, which will then overwrite the file with an OCR'd version of
the file and exit. At which point, the consumption process will begin
with the newly modified file.
The script's stdout and stderr will be logged line by line to the
webserver log, along with the exit code of the script.
### Post-consumption script {#post_consume_script}
Executed after the consumer has successfully processed a document and
has moved it into paperless. It receives the following environment
variables:
- `DOCUMENT_ID`
- `DOCUMENT_FILE_NAME`
- `DOCUMENT_CREATED`
- `DOCUMENT_MODIFIED`
- `DOCUMENT_ADDED`
- `DOCUMENT_SOURCE_PATH`
- `DOCUMENT_ARCHIVE_PATH`
- `DOCUMENT_THUMBNAIL_PATH`
- `DOCUMENT_DOWNLOAD_URL`
- `DOCUMENT_THUMBNAIL_URL`
- `DOCUMENT_CORRESPONDENT`
- `DOCUMENT_TAGS`
- `DOCUMENT_ORIGINAL_FILENAME`
The script can be in any language, but for a simple shell script
example, you can take a look at
[post-consumption-example.sh](https://github.com/paperless-ngx/paperless-ngx/blob/main/scripts/post-consumption-example.sh)
in this project.
The post consumption script cannot cancel the consumption process.
The script's stdout and stderr will be logged line by line to the
webserver log, along with the exit code of the script.
#### Docker
Assumed you have
`/home/foo/paperless-ngx/scripts/post-consumption-example.sh`.
You can pass that script into the consumer container via a host mount in
your `docker-compose.yml`.
```bash
...
consumer:
...
volumes:
...
- /home/paperless-ngx/scripts:/path/in/container/scripts/
...
```
Example (docker-compose.yml):
`- /home/foo/paperless-ngx/scripts:/usr/src/paperless/scripts`
which in turn requires the variable `PAPERLESS_POST_CONSUME_SCRIPT` in
`docker-compose.env` to point to
`/path/in/container/scripts/post-consumption-example.sh`.
Example (docker-compose.env):
`PAPERLESS_POST_CONSUME_SCRIPT=/usr/src/paperless/scripts/post-consumption-example.sh`
Troubleshooting:
- Monitor the docker-compose log
`cd ~/paperless-ngx; docker-compose logs -f`
- Check your script's permission e.g. in case of permission error
`sudo chmod 755 post-consumption-example.sh`
- Pipe your scripts's output to a log file e.g.
`echo "${DOCUMENT_ID}" | tee --append /usr/src/paperless/scripts/post-consumption-example.log`
## File name handling {#file_name_handling}
By default, paperless stores your documents in the media directory and
renames them using the identifier which it has assigned to each
document. You will end up getting files like `0000123.pdf` in your media
directory. This isn't necessarily a bad thing, because you normally
don't have to access these files manually. However, if you wish to name
your files differently, you can do that by adjusting the
`PAPERLESS_FILENAME_FORMAT` configuration option. Paperless adds the
correct file extension e.g. `.pdf`, `.jpg` automatically.
This variable allows you to configure the filename (folders are allowed)
using placeholders. For example, configuring this to
```bash
PAPERLESS_FILENAME_FORMAT={created_year}/{correspondent}/{title}
```
will create a directory structure as follows:
```
2019/
My bank/
Statement January.pdf
Statement February.pdf
2020/
My bank/
Statement January.pdf
Letter.pdf
Letter_01.pdf
Shoe store/
My new shoes.pdf
```
!!! warning
Do not manually move your files in the media folder. Paperless remembers
the last filename a document was stored as. If you do rename a file,
paperless will report your files as missing and won't be able to find
them.
Paperless provides the following placeholders within filenames:
- `{asn}`: The archive serial number of the document, or "none".
- `{correspondent}`: The name of the correspondent, or "none".
- `{document_type}`: The name of the document type, or "none".
- `{tag_list}`: A comma separated list of all tags assigned to the
document.
- `{title}`: The title of the document.
- `{created}`: The full date (ISO format) the document was created.
- `{created_year}`: Year created only, formatted as the year with
century.
- `{created_year_short}`: Year created only, formatted as the year
without century, zero padded.
- `{created_month}`: Month created only (number 01-12).
- `{created_month_name}`: Month created name, as per locale
- `{created_month_name_short}`: Month created abbreviated name, as per
locale
- `{created_day}`: Day created only (number 01-31).
- `{added}`: The full date (ISO format) the document was added to
paperless.
- `{added_year}`: Year added only.
- `{added_year_short}`: Year added only, formatted as the year without
century, zero padded.
- `{added_month}`: Month added only (number 01-12).
- `{added_month_name}`: Month added name, as per locale
- `{added_month_name_short}`: Month added abbreviated name, as per
locale
- `{added_day}`: Day added only (number 01-31).
Paperless will try to conserve the information from your database as
much as possible. However, some characters that you can use in document
titles and correspondent names (such as `: \ /` and a couple more) are
not allowed in filenames and will be replaced with dashes.
If paperless detects that two documents share the same filename,
paperless will automatically append `_01`, `_02`, etc to the filename.
This happens if all the placeholders in a filename evaluate to the same
value.
!!! tip
You can affect how empty placeholders are treated by changing the
following setting to [true]{.title-ref}.
```
PAPERLESS_FILENAME_FORMAT_REMOVE_NONE=True
```
Doing this results in all empty placeholders resolving to "" instead
of "none" as stated above. Spaces before empty placeholders are
removed as well, empty directories are omitted.
!!! tip
Paperless checks the filename of a document whenever it is saved.
Therefore, you need to update the filenames of your documents and move
them after altering this setting by invoking the
[`document renamer <utilities-renamer>`]().
!!! warning
Make absolutely sure you get the spelling of the placeholders right, or
else paperless will use the default naming scheme instead.
!!! caution
As of now, you could totally tell paperless to store your files anywhere
outside the media directory by setting
```
PAPERLESS_FILENAME_FORMAT=../../my/custom/location/{title}
```
However, keep in mind that inside docker, if files get stored outside of
the predefined volumes, they will be lost after a restart of paperless.
## Storage paths
One of the best things in Paperless is that you can not only access the
documents via the web interface, but also via the file system.
When as single storage layout is not sufficient for your use case,
storage paths come to the rescue. Storage paths allow you to configure
more precisely where each document is stored in the file system.
- Each storage path is a [PAPERLESS_FILENAME_FORMAT]{.title-ref} and
follows the rules described above
- Each document is assigned a storage path using the matching
algorithms described above, but can be overwritten at any time
For example, you could define the following two storage paths:
1. Normal communications are put into a folder structure sorted by
[year/correspondent]{.title-ref}
2. Communications with insurance companies are stored in a flat
structure with longer file names, but containing the full date of
the correspondence.
```
By Year = {created_year}/{correspondent}/{title}
Insurances = Insurances/{correspondent}/{created_year}-{created_month}-{created_day} {title}
```
If you then map these storage paths to the documents, you might get the
following result. For simplicity, [By Year]{.title-ref} defines the same
structure as in the previous example above.
```text
2019/ # By Year
My bank/
Statement January.pdf
Statement February.pdf
Insurances/ # Insurances
Healthcare 123/
2022-01-01 Statement January.pdf
2022-02-02 Letter.pdf
2022-02-03 Letter.pdf
Dental 456/
2021-12-01 New Conditions.pdf
```
!!! tip
Defining a storage path is optional. If no storage path is defined for a
document, the global [PAPERLESS_FILENAME_FORMAT]{.title-ref} is applied.
!!! warning
If you adjust the format of an existing storage path, old documents
don't get relocated automatically. You need to run the
[document renamer](/administration#renamer) to
adjust their pathes.
## Celery Monitoring {#celery-monitoring}
The monitoring tool
[Flower](https://flower.readthedocs.io/en/latest/index.html) can be used
to view more detailed information about the health of the celery workers
used for asynchronous tasks. This includes details on currently running,
queued and completed tasks, timing and more. Flower can also be used
with Prometheus, as it exports metrics. For details on its capabilities,
refer to the Flower documentation.
To configure Flower further, create a [flowerconfig.py]{.title-ref} and
place it into the [src/paperless]{.title-ref} directory. For a Docker
installation, you can use volumes to accomplish this:
```yaml
services:
# ...
webserver:
# ...
volumes:
- /path/to/my/flowerconfig.py:/usr/src/paperless/src/paperless/flowerconfig.py:ro
```
## Custom Container Initialization
The Docker image includes the ability to run custom user scripts during
startup. This could be utilized for installing additional tools or
Python packages, for example.
To utilize this, mount a folder containing your scripts to the custom
initialization directory, [/custom-cont-init.d]{.title-ref} and place
scripts you wish to run inside. For security, the folder and its
contents must be owned by [root]{.title-ref}. Additionally, scripts must
only be writable by [root]{.title-ref}.
Your scripts will be run directly before the webserver completes
startup. Scripts will be run by the [root]{.title-ref} user. This is an
advanced functionality with which you could break functionality or lose
data.
For example, using Docker Compose:
```yaml
services:
# ...
webserver:
# ...
volumes:
- /path/to/my/scripts:/custom-cont-init.d:ro
```
## MySQL Caveats {#mysql-caveats}
### Case Sensitivity
The database interface does not provide a method to configure a MySQL
database to be case sensitive. This would prevent a user from creating a
tag `Name` and `NAME` as they are considered the same.
Per Django documentation, to enable this requires manual intervention.
To enable case sensetive tables, you can execute the following command
against each table:
`ALTER TABLE <table_name> CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;`
You can also set the default for new tables (this does NOT affect
existing tables) with:
`ALTER DATABASE <db_name> CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;`

View File

@ -1,451 +0,0 @@
***************
Advanced topics
***************
Paperless offers a couple features that automate certain tasks and make your life
easier.
.. _advanced-matching:
Matching tags, correspondents, document types, and storage paths
################################################################
Paperless will compare the matching algorithms defined by every tag, correspondent,
document type, and storage path in your database to see if they apply to the text
in a document. In other words, if you define a tag called ``Home Utility``
that had a ``match`` property of ``bc hydro`` and a ``matching_algorithm`` of
``literal``, Paperless will automatically tag your newly-consumed document with
your ``Home Utility`` tag so long as the text ``bc hydro`` appears in the body
of the document somewhere.
The matching logic is quite powerful. It supports searching the text of your
document with different algorithms, and as such, some experimentation may be
necessary to get things right.
In order to have a tag, correspondent, document type, or storage path assigned
automatically to newly consumed documents, assign a match and matching algorithm
using the web interface. These settings define when to assign tags, correspondents,
document types, and storage paths to documents.
The following algorithms are available:
* **Any:** Looks for any occurrence of any word provided in match in the PDF.
If you define the match as ``Bank1 Bank2``, it will match documents containing
either of these terms.
* **All:** Requires that every word provided appears in the PDF, albeit not in the
order provided.
* **Literal:** Matches only if the match appears exactly as provided (i.e. preserve ordering) in the PDF.
* **Regular expression:** Parses the match as a regular expression and tries to
find a match within the document.
* **Fuzzy match:** I don't know. Look at the source.
* **Auto:** Tries to automatically match new documents. This does not require you
to set a match. See the notes below.
When using the *any* or *all* matching algorithms, you can search for terms
that consist of multiple words by enclosing them in double quotes. For example,
defining a match text of ``"Bank of America" BofA`` using the *any* algorithm,
will match documents that contain either "Bank of America" or "BofA", but will
not match documents containing "Bank of South America".
Then just save your tag, correspondent, document type, or storage path and run
another document through the consumer. Once complete, you should see the
newly-created document, automatically tagged with the appropriate data.
.. _advanced-automatic_matching:
Automatic matching
==================
Paperless-ngx comes with a new matching algorithm called *Auto*. This matching
algorithm tries to assign tags, correspondents, document types, and storage paths
to your documents based on how you have already assigned these on existing documents.
It uses a neural network under the hood.
If, for example, all your bank statements of your account 123 at the Bank of
America are tagged with the tag "bofa_123" and the matching algorithm of this
tag is set to *Auto*, this neural network will examine your documents and
automatically learn when to assign this tag.
Paperless tries to hide much of the involved complexity with this approach.
However, there are a couple caveats you need to keep in mind when using this
feature:
* Changes to your documents are not immediately reflected by the matching
algorithm. The neural network needs to be *trained* on your documents after
changes. Paperless periodically (default: once each hour) checks for changes
and does this automatically for you.
* The Auto matching algorithm only takes documents into account which are NOT
placed in your inbox (i.e. have any inbox tags assigned to them). This ensures
that the neural network only learns from documents which you have correctly
tagged before.
* The matching algorithm can only work if there is a correlation between the
tag, correspondent, document type, or storage path and the document itself.
Your bank statements usually contain your bank account number and the name
of the bank, so this works reasonably well, However, tags such as "TODO"
cannot be automatically assigned.
* The matching algorithm needs a reasonable number of documents to identify when
to assign tags, correspondents, storage paths, and types. If one out of a
thousand documents has the correspondent "Very obscure web shop I bought
something five years ago", it will probably not assign this correspondent
automatically if you buy something from them again. The more documents, the better.
* Paperless also needs a reasonable amount of negative examples to decide when
not to assign a certain tag, correspondent, document type, or storage path. This will
usually be the case as you start filling up paperless with documents.
Example: If all your documents are either from "Webshop" and "Bank", paperless
will assign one of these correspondents to ANY new document, if both are set
to automatic matching.
Hooking into the consumption process
####################################
Sometimes you may want to do something arbitrary whenever a document is
consumed. Rather than try to predict what you may want to do, Paperless lets
you execute scripts of your own choosing just before or after a document is
consumed using a couple simple hooks.
Just write a script, put it somewhere that Paperless can read & execute, and
then put the path to that script in ``paperless.conf`` or ``docker-compose.env`` with the variable name
of either ``PAPERLESS_PRE_CONSUME_SCRIPT`` or
``PAPERLESS_POST_CONSUME_SCRIPT``.
.. important::
These scripts are executed in a **blocking** process, which means that if
a script takes a long time to run, it can significantly slow down your
document consumption flow. If you want things to run asynchronously,
you'll have to fork the process in your script and exit.
Pre-consumption script
======================
Executed after the consumer sees a new document in the consumption folder, but
before any processing of the document is performed. This script can access the
following relevant environment variables set:
* ``DOCUMENT_SOURCE_PATH``
A simple but common example for this would be creating a simple script like
this:
``/usr/local/bin/ocr-pdf``
.. code:: bash
#!/usr/bin/env bash
pdf2pdfocr.py -i ${DOCUMENT_SOURCE_PATH}
``/etc/paperless.conf``
.. code:: bash
...
PAPERLESS_PRE_CONSUME_SCRIPT="/usr/local/bin/ocr-pdf"
...
This will pass the path to the document about to be consumed to ``/usr/local/bin/ocr-pdf``,
which will in turn call `pdf2pdfocr.py`_ on your document, which will then
overwrite the file with an OCR'd version of the file and exit. At which point,
the consumption process will begin with the newly modified file.
The script's stdout and stderr will be logged line by line to the webserver log, along
with the exit code of the script.
.. _pdf2pdfocr.py: https://github.com/LeoFCardoso/pdf2pdfocr
.. _advanced-post_consume_script:
Post-consumption script
=======================
Executed after the consumer has successfully processed a document and has moved it
into paperless. It receives the following environment variables:
* ``DOCUMENT_ID``
* ``DOCUMENT_FILE_NAME``
* ``DOCUMENT_CREATED``
* ``DOCUMENT_MODIFIED``
* ``DOCUMENT_ADDED``
* ``DOCUMENT_SOURCE_PATH``
* ``DOCUMENT_ARCHIVE_PATH``
* ``DOCUMENT_THUMBNAIL_PATH``
* ``DOCUMENT_DOWNLOAD_URL``
* ``DOCUMENT_THUMBNAIL_URL``
* ``DOCUMENT_CORRESPONDENT``
* ``DOCUMENT_TAGS``
* ``DOCUMENT_ORIGINAL_FILENAME``
The script can be in any language, but for a simple shell script
example, you can take a look at `post-consumption-example.sh`_ in this project.
The post consumption script cannot cancel the consumption process.
The script's stdout and stderr will be logged line by line to the webserver log, along
with the exit code of the script.
Docker
------
Assumed you have ``/home/foo/paperless-ngx/scripts/post-consumption-example.sh``.
You can pass that script into the consumer container via a host mount in your ``docker-compose.yml``.
.. code:: bash
...
consumer:
...
volumes:
...
- /home/paperless-ngx/scripts:/path/in/container/scripts/
...
Example (docker-compose.yml): ``- /home/foo/paperless-ngx/scripts:/usr/src/paperless/scripts``
which in turn requires the variable ``PAPERLESS_POST_CONSUME_SCRIPT`` in ``docker-compose.env`` to point to ``/path/in/container/scripts/post-consumption-example.sh``.
Example (docker-compose.env): ``PAPERLESS_POST_CONSUME_SCRIPT=/usr/src/paperless/scripts/post-consumption-example.sh``
Troubleshooting:
- Monitor the docker-compose log ``cd ~/paperless-ngx; docker-compose logs -f``
- Check your script's permission e.g. in case of permission error ``sudo chmod 755 post-consumption-example.sh``
- Pipe your scripts's output to a log file e.g. ``echo "${DOCUMENT_ID}" | tee --append /usr/src/paperless/scripts/post-consumption-example.log``
.. _post-consumption-example.sh: https://github.com/paperless-ngx/paperless-ngx/blob/main/scripts/post-consumption-example.sh
.. _advanced-file_name_handling:
File name handling
##################
By default, paperless stores your documents in the media directory and renames them
using the identifier which it has assigned to each document. You will end up getting
files like ``0000123.pdf`` in your media directory. This isn't necessarily a bad
thing, because you normally don't have to access these files manually. However, if
you wish to name your files differently, you can do that by adjusting the
``PAPERLESS_FILENAME_FORMAT`` configuration option. Paperless adds the correct
file extension e.g. ``.pdf``, ``.jpg`` automatically.
This variable allows you to configure the filename (folders are allowed) using
placeholders. For example, configuring this to
.. code:: bash
PAPERLESS_FILENAME_FORMAT={created_year}/{correspondent}/{title}
will create a directory structure as follows:
.. code::
2019/
My bank/
Statement January.pdf
Statement February.pdf
2020/
My bank/
Statement January.pdf
Letter.pdf
Letter_01.pdf
Shoe store/
My new shoes.pdf
.. danger::
Do not manually move your files in the media folder. Paperless remembers the
last filename a document was stored as. If you do rename a file, paperless will
report your files as missing and won't be able to find them.
Paperless provides the following placeholders within filenames:
* ``{asn}``: The archive serial number of the document, or "none".
* ``{correspondent}``: The name of the correspondent, or "none".
* ``{document_type}``: The name of the document type, or "none".
* ``{tag_list}``: A comma separated list of all tags assigned to the document.
* ``{title}``: The title of the document.
* ``{created}``: The full date (ISO format) the document was created.
* ``{created_year}``: Year created only, formatted as the year with century.
* ``{created_year_short}``: Year created only, formatted as the year without century, zero padded.
* ``{created_month}``: Month created only (number 01-12).
* ``{created_month_name}``: Month created name, as per locale
* ``{created_month_name_short}``: Month created abbreviated name, as per locale
* ``{created_day}``: Day created only (number 01-31).
* ``{added}``: The full date (ISO format) the document was added to paperless.
* ``{added_year}``: Year added only.
* ``{added_year_short}``: Year added only, formatted as the year without century, zero padded.
* ``{added_month}``: Month added only (number 01-12).
* ``{added_month_name}``: Month added name, as per locale
* ``{added_month_name_short}``: Month added abbreviated name, as per locale
* ``{added_day}``: Day added only (number 01-31).
Paperless will try to conserve the information from your database as much as possible.
However, some characters that you can use in document titles and correspondent names (such
as ``: \ /`` and a couple more) are not allowed in filenames and will be replaced with dashes.
If paperless detects that two documents share the same filename, paperless will automatically
append ``_01``, ``_02``, etc to the filename. This happens if all the placeholders in a filename
evaluate to the same value.
.. hint::
You can affect how empty placeholders are treated by changing the following setting to
`true`.
.. code::
PAPERLESS_FILENAME_FORMAT_REMOVE_NONE=True
Doing this results in all empty placeholders resolving to "" instead of "none" as stated above.
Spaces before empty placeholders are removed as well, empty directories are omitted.
.. hint::
Paperless checks the filename of a document whenever it is saved. Therefore,
you need to update the filenames of your documents and move them after altering
this setting by invoking the :ref:`document renamer <utilities-renamer>`.
.. warning::
Make absolutely sure you get the spelling of the placeholders right, or else
paperless will use the default naming scheme instead.
.. caution::
As of now, you could totally tell paperless to store your files anywhere outside
the media directory by setting
.. code::
PAPERLESS_FILENAME_FORMAT=../../my/custom/location/{title}
However, keep in mind that inside docker, if files get stored outside of the
predefined volumes, they will be lost after a restart of paperless.
Storage paths
#############
One of the best things in Paperless is that you can not only access the documents via the
web interface, but also via the file system.
When as single storage layout is not sufficient for your use case, storage paths come to
the rescue. Storage paths allow you to configure more precisely where each document is stored
in the file system.
- Each storage path is a `PAPERLESS_FILENAME_FORMAT` and follows the rules described above
- Each document is assigned a storage path using the matching algorithms described above, but
can be overwritten at any time
For example, you could define the following two storage paths:
1. Normal communications are put into a folder structure sorted by `year/correspondent`
2. Communications with insurance companies are stored in a flat structure with longer file names,
but containing the full date of the correspondence.
.. code::
By Year = {created_year}/{correspondent}/{title}
Insurances = Insurances/{correspondent}/{created_year}-{created_month}-{created_day} {title}
If you then map these storage paths to the documents, you might get the following result.
For simplicity, `By Year` defines the same structure as in the previous example above.
.. code:: text
2019/ # By Year
My bank/
Statement January.pdf
Statement February.pdf
Insurances/ # Insurances
Healthcare 123/
2022-01-01 Statement January.pdf
2022-02-02 Letter.pdf
2022-02-03 Letter.pdf
Dental 456/
2021-12-01 New Conditions.pdf
.. hint::
Defining a storage path is optional. If no storage path is defined for a document, the global
`PAPERLESS_FILENAME_FORMAT` is applied.
.. caution::
If you adjust the format of an existing storage path, old documents don't get relocated automatically.
You need to run the :ref:`document renamer <utilities-renamer>` to adjust their pathes.
.. _advanced-celery-monitoring:
Celery Monitoring
#################
The monitoring tool `Flower <https://flower.readthedocs.io/en/latest/index.html>`_ can be used to view more
detailed information about the health of the celery workers used for asynchronous tasks. This includes details
on currently running, queued and completed tasks, timing and more. Flower can also be used with Prometheus, as it
exports metrics. For details on its capabilities, refer to the Flower documentation.
To configure Flower further, create a `flowerconfig.py` and place it into the `src/paperless` directory. For
a Docker installation, you can use volumes to accomplish this:
.. code:: yaml
services:
# ...
webserver:
# ...
volumes:
- /path/to/my/flowerconfig.py:/usr/src/paperless/src/paperless/flowerconfig.py:ro
Custom Container Initialization
###############################
The Docker image includes the ability to run custom user scripts during startup. This could be
utilized for installing additional tools or Python packages, for example.
To utilize this, mount a folder containing your scripts to the custom initialization directory, `/custom-cont-init.d`
and place scripts you wish to run inside. For security, the folder must be owned by `root` and should have permissions
of `a=rx`. Additionally, scripts must only be writable by `root`.
Your scripts will be run directly before the webserver completes startup. Scripts will be run by the `root` user.
If you would like to switch users, the utility `gosu` is available and preferred over `sudo`.
This is an advanced functionality with which you could break functionality or lose data. If you experience issues,
please disable any custom scripts and try again before reporting an issue.
For example, using Docker Compose:
.. code:: yaml
services:
# ...
webserver:
# ...
volumes:
- /path/to/my/scripts:/custom-cont-init.d:ro
.. _advanced-mysql-caveats:
MySQL Caveats
#############
Case Sensitivity
================
The database interface does not provide a method to configure a MySQL database to
be case sensitive. This would prevent a user from creating a tag ``Name`` and ``NAME``
as they are considered the same.
Per Django documentation, to enable this requires manual intervention. To enable
case sensetive tables, you can execute the following command against each table:
``ALTER TABLE <table_name> CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;``
You can also set the default for new tables (this does NOT affect existing tables) with:
``ALTER DATABASE <db_name> CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;``

319
docs/api.md Normal file
View File

@ -0,0 +1,319 @@
# The REST API
Paperless makes use of the [Django REST
Framework](http://django-rest-framework.org/) standard API interface. It
provides a browsable API for most of its endpoints, which you can
inspect at `http://<paperless-host>:<port>/api/`. This also documents
most of the available filters and ordering fields.
The API provides 5 main endpoints:
- `/api/documents/`: Full CRUD support, except POSTing new documents.
See below.
- `/api/correspondents/`: Full CRUD support.
- `/api/document_types/`: Full CRUD support.
- `/api/logs/`: Read-Only.
- `/api/tags/`: Full CRUD support.
- `/api/mail_accounts/`: Full CRUD support.
- `/api/mail_rules/`: Full CRUD support.
All of these endpoints except for the logging endpoint allow you to
fetch, edit and delete individual objects by appending their primary key
to the path, for example `/api/documents/454/`.
The objects served by the document endpoint contain the following
fields:
- `id`: ID of the document. Read-only.
- `title`: Title of the document.
- `content`: Plain text content of the document.
- `tags`: List of IDs of tags assigned to this document, or empty
list.
- `document_type`: Document type of this document, or null.
- `correspondent`: Correspondent of this document or null.
- `created`: The date time at which this document was created.
- `created_date`: The date (YYYY-MM-DD) at which this document was
created. Optional. If also passed with created, this is ignored.
- `modified`: The date at which this document was last edited in
paperless. Read-only.
- `added`: The date at which this document was added to paperless.
Read-only.
- `archive_serial_number`: The identifier of this document in a
physical document archive.
- `original_file_name`: Verbose filename of the original document.
Read-only.
- `archived_file_name`: Verbose filename of the archived document.
Read-only. Null if no archived document is available.
## Downloading documents
In addition to that, the document endpoint offers these additional
actions on individual documents:
- `/api/documents/<pk>/download/`: Download the document.
- `/api/documents/<pk>/preview/`: Display the document inline, without
downloading it.
- `/api/documents/<pk>/thumb/`: Download the PNG thumbnail of a
document.
Paperless generates archived PDF/A documents from consumed files and
stores both the original files as well as the archived files. By
default, the endpoints for previews and downloads serve the archived
file, if it is available. Otherwise, the original file is served. Some
document cannot be archived.
The endpoints correctly serve the response header fields
`Content-Disposition` and `Content-Type` to indicate the filename for
download and the type of content of the document.
In order to download or preview the original document when an archived
document is available, supply the query parameter `original=true`.
!!! tip
Paperless used to provide these functionality at `/fetch/<pk>/preview`,
`/fetch/<pk>/thumb` and `/fetch/<pk>/doc`. Redirects to the new URLs are
in place. However, if you use these old URLs to access documents, you
should update your app or script to use the new URLs.
## Getting document metadata
The api also has an endpoint to retrieve read-only metadata about
specific documents. this information is not served along with the
document objects, since it requires reading files and would therefore
slow down document lists considerably.
Access the metadata of a document with an ID `id` at
`/api/documents/<id>/metadata/`.
The endpoint reports the following data:
- `original_checksum`: MD5 checksum of the original document.
- `original_size`: Size of the original document, in bytes.
- `original_mime_type`: Mime type of the original document.
- `media_filename`: Current filename of the document, under which it
is stored inside the media directory.
- `has_archive_version`: True, if this document is archived, false
otherwise.
- `original_metadata`: A list of metadata associated with the original
document. See below.
- `archive_checksum`: MD5 checksum of the archived document, or null.
- `archive_size`: Size of the archived document in bytes, or null.
- `archive_metadata`: Metadata associated with the archived document,
or null. See below.
File metadata is reported as a list of objects in the following form:
```json
[
{
"namespace": "http://ns.adobe.com/pdf/1.3/",
"prefix": "pdf",
"key": "Producer",
"value": "SparklePDF, Fancy edition"
}
]
```
`namespace` and `prefix` can be null. The actual metadata reported
depends on the file type and the metadata available in that specific
document. Paperless only reports PDF metadata at this point.
## Authorization
The REST api provides three different forms of authentication.
1. Basic authentication
Authorize by providing a HTTP header in the form
```
Authorization: Basic <credentials>
```
where `credentials` is a base64-encoded string of
`<username>:<password>`
2. Session authentication
When you're logged into paperless in your browser, you're
automatically logged into the API as well and don't need to provide
any authorization headers.
3. Token authentication
Paperless also offers an endpoint to acquire authentication tokens.
POST a username and password as a form or json string to
`/api/token/` and paperless will respond with a token, if the login
data is correct. This token can be used to authenticate other
requests with the following HTTP header:
```
Authorization: Token <token>
```
Tokens can be managed and revoked in the paperless admin.
## Searching for documents
Full text searching is available on the `/api/documents/` endpoint. Two
specific query parameters cause the API to return full text search
results:
- `/api/documents/?query=your%20search%20query`: Search for a document
using a full text query. For details on the syntax, see
`basic-usage_searching`{.interpreted-text role="ref"}.
- `/api/documents/?more_like=1234`: Search for documents similar to
the document with id 1234.
Pagination works exactly the same as it does for normal requests on this
endpoint.
Certain limitations apply to full text queries:
- Results are always sorted by search score. The results matching the
query best will show up first.
- Only a small subset of filtering parameters are supported.
Furthermore, each returned document has an additional `__search_hit__`
attribute with various information about the search results:
```
{
"count": 31,
"next": "http://localhost:8000/api/documents/?page=2&query=test",
"previous": null,
"results": [
...
{
"id": 123,
"title": "title",
"content": "content",
...
"__search_hit__": {
"score": 0.343,
"highlights": "text <span class="match">Test</span> text",
"rank": 23
}
},
...
]
}
```
- `score` is an indication how well this document matches the query
relative to the other search results.
- `highlights` is an excerpt from the document content and highlights
the search terms with `<span>` tags as shown above.
- `rank` is the index of the search results. The first result will
have rank 0.
### `/api/search/autocomplete/`
Get auto completions for a partial search term.
Query parameters:
- `term`: The incomplete term.
- `limit`: Amount of results. Defaults to 10.
Results returned by the endpoint are ordered by importance of the term
in the document index. The first result is the term that has the highest
Tf/Idf score in the index.
```json
["term1", "term3", "term6", "term4"]
```
## POSTing documents {#api-file_uploads}
The API provides a special endpoint for file uploads:
`/api/documents/post_document/`
POST a multipart form to this endpoint, where the form field `document`
contains the document that you want to upload to paperless. The filename
is sanitized and then used to store the document in a temporary
directory, and the consumer will be instructed to consume the document
from there.
The endpoint supports the following optional form fields:
- `title`: Specify a title that the consumer should use for the
document.
- `created`: Specify a DateTime where the document was created (e.g.
"2016-04-19" or "2016-04-19 06:15:00+02:00").
- `correspondent`: Specify the ID of a correspondent that the consumer
should use for the document.
- `document_type`: Similar to correspondent.
- `tags`: Similar to correspondent. Specify this multiple times to
have multiple tags added to the document.
The endpoint will immediately return "OK" if the document consumption
process was started successfully. No additional status information about
the consumption process itself is available, since that happens in a
different process.
## API Versioning
The REST API is versioned since Paperless-ngx 1.3.0.
- Versioning ensures that changes to the API don't break older
clients.
- Clients specify the specific version of the API they wish to use
with every request and Paperless will handle the request using the
specified API version.
- Even if the underlying data model changes, older API versions will
always serve compatible data.
- If no version is specified, Paperless will serve version 1 to ensure
compatibility with older clients that do not request a specific API
version.
API versions are specified by submitting an additional HTTP `Accept`
header with every request:
```
Accept: application/json; version=6
```
If an invalid version is specified, Paperless 1.3.0 will respond with
"406 Not Acceptable" and an error message in the body. Earlier
versions of Paperless will serve API version 1 regardless of whether a
version is specified via the `Accept` header.
If a client wishes to verify whether it is compatible with any given
server, the following procedure should be performed:
1. Perform an _authenticated_ request against any API endpoint. If the
server is on version 1.3.0 or newer, the server will add two custom
headers to the response:
```
X-Api-Version: 2
X-Version: 1.3.0
```
2. Determine whether the client is compatible with this server based on
the presence/absence of these headers and their values if present.
### API Changelog
#### Version 1
Initial API version.
#### Version 2
- Added field `Tag.color`. This read/write string field contains a hex
color such as `#a6cee3`.
- Added read-only field `Tag.text_color`. This field contains the text
color to use for a specific tag, which is either black or white
depending on the brightness of `Tag.color`.
- Removed field `Tag.colour`.

View File

@ -1,303 +0,0 @@
************
The REST API
************
Paperless makes use of the `Django REST Framework`_ standard API interface.
It provides a browsable API for most of its endpoints, which you can inspect
at ``http://<paperless-host>:<port>/api/``. This also documents most of the
available filters and ordering fields.
.. _Django REST Framework: http://django-rest-framework.org/
The API provides 5 main endpoints:
* ``/api/documents/``: Full CRUD support, except POSTing new documents. See below.
* ``/api/correspondents/``: Full CRUD support.
* ``/api/document_types/``: Full CRUD support.
* ``/api/logs/``: Read-Only.
* ``/api/tags/``: Full CRUD support.
All of these endpoints except for the logging endpoint
allow you to fetch, edit and delete individual objects
by appending their primary key to the path, for example ``/api/documents/454/``.
The objects served by the document endpoint contain the following fields:
* ``id``: ID of the document. Read-only.
* ``title``: Title of the document.
* ``content``: Plain text content of the document.
* ``tags``: List of IDs of tags assigned to this document, or empty list.
* ``document_type``: Document type of this document, or null.
* ``correspondent``: Correspondent of this document or null.
* ``created``: The date time at which this document was created.
* ``created_date``: The date (YYYY-MM-DD) at which this document was created. Optional. If also passed with created, this is ignored.
* ``modified``: The date at which this document was last edited in paperless. Read-only.
* ``added``: The date at which this document was added to paperless. Read-only.
* ``archive_serial_number``: The identifier of this document in a physical document archive.
* ``original_file_name``: Verbose filename of the original document. Read-only.
* ``archived_file_name``: Verbose filename of the archived document. Read-only. Null if no archived document is available.
Downloading documents
#####################
In addition to that, the document endpoint offers these additional actions on
individual documents:
* ``/api/documents/<pk>/download/``: Download the document.
* ``/api/documents/<pk>/preview/``: Display the document inline,
without downloading it.
* ``/api/documents/<pk>/thumb/``: Download the PNG thumbnail of a document.
Paperless generates archived PDF/A documents from consumed files and stores both
the original files as well as the archived files. By default, the endpoints
for previews and downloads serve the archived file, if it is available.
Otherwise, the original file is served.
Some document cannot be archived.
The endpoints correctly serve the response header fields ``Content-Disposition``
and ``Content-Type`` to indicate the filename for download and the type of content of
the document.
In order to download or preview the original document when an archived document is available,
supply the query parameter ``original=true``.
.. hint::
Paperless used to provide these functionality at ``/fetch/<pk>/preview``,
``/fetch/<pk>/thumb`` and ``/fetch/<pk>/doc``. Redirects to the new URLs
are in place. However, if you use these old URLs to access documents, you
should update your app or script to use the new URLs.
Getting document metadata
#########################
The api also has an endpoint to retrieve read-only metadata about specific documents. this
information is not served along with the document objects, since it requires reading
files and would therefore slow down document lists considerably.
Access the metadata of a document with an ID ``id`` at ``/api/documents/<id>/metadata/``.
The endpoint reports the following data:
* ``original_checksum``: MD5 checksum of the original document.
* ``original_size``: Size of the original document, in bytes.
* ``original_mime_type``: Mime type of the original document.
* ``media_filename``: Current filename of the document, under which it is stored inside the media directory.
* ``has_archive_version``: True, if this document is archived, false otherwise.
* ``original_metadata``: A list of metadata associated with the original document. See below.
* ``archive_checksum``: MD5 checksum of the archived document, or null.
* ``archive_size``: Size of the archived document in bytes, or null.
* ``archive_metadata``: Metadata associated with the archived document, or null. See below.
File metadata is reported as a list of objects in the following form:
.. code:: json
[
{
"namespace": "http://ns.adobe.com/pdf/1.3/",
"prefix": "pdf",
"key": "Producer",
"value": "SparklePDF, Fancy edition"
},
]
``namespace`` and ``prefix`` can be null. The actual metadata reported depends on the file type and the metadata
available in that specific document. Paperless only reports PDF metadata at this point.
Authorization
#############
The REST api provides three different forms of authentication.
1. Basic authentication
Authorize by providing a HTTP header in the form
.. code::
Authorization: Basic <credentials>
where ``credentials`` is a base64-encoded string of ``<username>:<password>``
2. Session authentication
When you're logged into paperless in your browser, you're automatically
logged into the API as well and don't need to provide any authorization
headers.
3. Token authentication
Paperless also offers an endpoint to acquire authentication tokens.
POST a username and password as a form or json string to ``/api/token/``
and paperless will respond with a token, if the login data is correct.
This token can be used to authenticate other requests with the
following HTTP header:
.. code::
Authorization: Token <token>
Tokens can be managed and revoked in the paperless admin.
Searching for documents
#######################
Full text searching is available on the ``/api/documents/`` endpoint. Two specific
query parameters cause the API to return full text search results:
* ``/api/documents/?query=your%20search%20query``: Search for a document using a full text query.
For details on the syntax, see :ref:`basic-usage_searching`.
* ``/api/documents/?more_like=1234``: Search for documents similar to the document with id 1234.
Pagination works exactly the same as it does for normal requests on this endpoint.
Certain limitations apply to full text queries:
* Results are always sorted by search score. The results matching the query best will show up first.
* Only a small subset of filtering parameters are supported.
Furthermore, each returned document has an additional ``__search_hit__`` attribute with various information
about the search results:
.. code::
{
"count": 31,
"next": "http://localhost:8000/api/documents/?page=2&query=test",
"previous": null,
"results": [
...
{
"id": 123,
"title": "title",
"content": "content",
...
"__search_hit__": {
"score": 0.343,
"highlights": "text <span class=\"match\">Test</span> text",
"rank": 23
}
},
...
]
}
* ``score`` is an indication how well this document matches the query relative to the other search results.
* ``highlights`` is an excerpt from the document content and highlights the search terms with ``<span>`` tags as shown above.
* ``rank`` is the index of the search results. The first result will have rank 0.
``/api/search/autocomplete/``
=============================
Get auto completions for a partial search term.
Query parameters:
* ``term``: The incomplete term.
* ``limit``: Amount of results. Defaults to 10.
Results returned by the endpoint are ordered by importance of the term in the
document index. The first result is the term that has the highest Tf/Idf score
in the index.
.. code:: json
[
"term1",
"term3",
"term6",
"term4"
]
.. _api-file_uploads:
POSTing documents
#################
The API provides a special endpoint for file uploads:
``/api/documents/post_document/``
POST a multipart form to this endpoint, where the form field ``document`` contains
the document that you want to upload to paperless. The filename is sanitized and
then used to store the document in a temporary directory, and the consumer will
be instructed to consume the document from there.
The endpoint supports the following optional form fields:
* ``title``: Specify a title that the consumer should use for the document.
* ``created``: Specify a DateTime where the document was created (e.g. "2016-04-19" or "2016-04-19 06:15:00+02:00").
* ``correspondent``: Specify the ID of a correspondent that the consumer should use for the document.
* ``document_type``: Similar to correspondent.
* ``tags``: Similar to correspondent. Specify this multiple times to have multiple tags added
to the document.
The endpoint will immediately return "OK" if the document consumption process
was started successfully. No additional status information about the consumption
process itself is available, since that happens in a different process.
.. _api-versioning:
API Versioning
##############
The REST API is versioned since Paperless-ngx 1.3.0.
* Versioning ensures that changes to the API don't break older clients.
* Clients specify the specific version of the API they wish to use with every request and Paperless will handle the request using the specified API version.
* Even if the underlying data model changes, older API versions will always serve compatible data.
* If no version is specified, Paperless will serve version 1 to ensure compatibility with older clients that do not request a specific API version.
API versions are specified by submitting an additional HTTP ``Accept`` header with every request:
.. code::
Accept: application/json; version=6
If an invalid version is specified, Paperless 1.3.0 will respond with "406 Not Acceptable" and an error message in the body.
Earlier versions of Paperless will serve API version 1 regardless of whether a version is specified via the ``Accept`` header.
If a client wishes to verify whether it is compatible with any given server, the following procedure should be performed:
1. Perform an *authenticated* request against any API endpoint. If the server is on version 1.3.0 or newer, the server will
add two custom headers to the response:
.. code::
X-Api-Version: 2
X-Version: 1.3.0
2. Determine whether the client is compatible with this server based on the presence/absence of these headers and their values if present.
API Changelog
=============
Version 1
---------
Initial API version.
Version 2
---------
* Added field ``Tag.color``. This read/write string field contains a hex color such as ``#a6cee3``.
* Added read-only field ``Tag.text_color``. This field contains the text color to use for a specific tag, which is either black or white depending on the brightness of ``Tag.color``.
* Removed field ``Tag.colour``.

36
docs/assets/extra.css Normal file
View File

@ -0,0 +1,36 @@
:root > * {
--md-primary-fg-color: #17541f;
--md-primary-fg-color--dark: #17541f;
--md-primary-fg-color--light: #17541f;
--md-accent-fg-color: #2b8a38;
--md-typeset-a-color: #21652a;
}
[data-md-color-scheme="slate"] {
--md-hue: 222;
}
@media (min-width: 400px) {
.grid-left {
width: 33%;
float: left;
}
.grid-right {
width: 62%;
margin-left: 4%;
float: left;
}
}
.grid-left > p {
margin-bottom: 2rem;
}
.grid-right p {
margin: 0;
}
.index-callout {
margin-right: .5rem;
}

12
docs/assets/logo.svg Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 27.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 1000 1000" style="enable-background:new 0 0 1000 1000;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
</style>
<path class="st0" d="M299,891.7c-4.2-19.8-12.5-59.6-13.6-59.6c-176.7-105.7-155.8-288.7-97.3-393.4
c12.5,131.8,245.8,222.8,109.8,383.9c-1.1,2,6.2,27.2,12.5,50.2c27.2-46,68-101.4,65.8-106.7C208.9,358.2,731.9,326.9,840.6,73.7
c49.1,244.8-25.1,623.5-445.5,719.7c-2,1.1-76.3,131.8-79.5,132.9c0-2-31.4-1.1-27.2-11.5C290.7,908.4,294.8,900.1,299,891.7
L299,891.7z M293.8,793.4c53.3-61.8-9.4-167.4-47.1-201.9C310.5,701.3,306.3,765.1,293.8,793.4L293.8,793.4z"/>
</svg>

After

Width:  |  Height:  |  Size: 869 B

View File

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 27.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 2962.2 860.2" style="enable-background:new 0 0 2962.2 860.2;" xml:space="preserve">
<style type="text/css">
.st0{fill:#17541F;stroke:#000000;stroke-miterlimit:10;}
</style>
<path d="M1055.6,639.7v-20.6c-18,20-43.1,30.1-75.4,30.1c-22.4,0-42.8-5.8-61-17.5c-18.3-11.7-32.5-27.8-42.9-48.3
c-10.3-20.5-15.5-43.3-15.5-68.4c0-25.1,5.2-48,15.5-68.5s24.6-36.6,42.9-48.3s38.6-17.5,61-17.5c32.3,0,57.5,10,75.4,30.1v-20.6
h85.3v249.6L1055.6,639.7L1055.6,639.7z M1059.1,514.9c0-17.4-5.2-31.9-15.5-43.8c-10.3-11.8-23.9-17.7-40.6-17.7
c-16.8,0-30.2,5.9-40.4,17.7c-10.2,11.8-15.3,26.4-15.3,43.8c0,17.4,5.1,31.9,15.3,43.8c10.2,11.8,23.6,17.7,40.4,17.7
c16.8,0,30.3-5.9,40.6-17.7C1054,546.9,1059.1,532.3,1059.1,514.9z"/>
<path d="M1417.8,398.2c18.3,11.7,32.5,27.8,42.9,48.3c10.3,20.5,15.5,43.3,15.5,68.5c0,25.1-5.2,48-15.5,68.4
c-10.3,20.5-24.6,36.6-42.9,48.3s-38.6,17.5-61,17.5c-32.3,0-57.5-10-75.4-30.1v165.6h-85.3V390.2h85.3v20.6
c18-20,43.1-30.1,75.4-30.1C1379.2,380.7,1399.5,386.6,1417.8,398.2z M1389.5,514.9c0-17.4-5.1-31.9-15.3-43.8
c-10.2-11.8-23.6-17.7-40.4-17.7s-30.2,5.9-40.4,17.7c-10.2,11.8-15.3,26.4-15.3,43.8c0,17.4,5.1,31.9,15.3,43.8
c10.2,11.8,23.6,17.7,40.4,17.7s30.2-5.9,40.4-17.7S1389.5,532.3,1389.5,514.9z"/>
<path d="M1713.6,555.3l53,49.4c-28.1,29.6-66.7,44.4-115.8,44.4c-28.1,0-53-5.8-74.5-17.5s-38.2-27.7-49.8-48
c-11.7-20.3-17.7-43.2-18-68.7c0-24.8,5.9-47.5,17.7-68c11.8-20.5,28.1-36.7,48.7-48.5s43.5-17.7,68.7-17.7
c24.8,0,47.6,6.1,68.2,18.2s37,29.5,49.1,52.3c12.1,22.7,18.2,49.1,18.2,79l-0.4,11.7h-181.8c3.6,11.4,10.5,20.7,20.9,28.1
c10.3,7.3,21.3,11,33,11c14.4,0,26.3-2.2,35.7-6.5C1695.8,570.1,1704.9,563.7,1713.6,555.3z M1596.9,486.2h92.9
c-2.1-12.3-7.5-22.1-16.2-29.4s-18.7-11-30.1-11s-21.5,3.7-30.3,11S1599,473.9,1596.9,486.2z"/>
<path d="M1908.8,418.4c7.8-10.8,17.2-19,28.3-24.7s22-8.5,32.8-8.5c11.4,0,20,1.6,26,4.9l-10.8,72.7c-8.4-2.1-15.7-3.1-22-3.1
c-17.1,0-30.4,4.3-39.9,12.8c-9.6,8.5-14.4,24.2-14.4,46.9v120.3h-85.3V390.2h85.3V418.4L1908.8,418.4z"/>
<path d="M2113,258.2v381.5h-85.3V258.2H2113z"/>
<path d="M2360.8,555.3l53,49.4c-28.1,29.6-66.7,44.4-115.8,44.4c-28.1,0-53-5.8-74.5-17.5s-38.2-27.7-49.8-48
c-11.7-20.3-17.7-43.2-18-68.7c0-24.8,5.9-47.5,17.7-68s28.1-36.7,48.7-48.5c20.6-11.8,43.5-17.7,68.7-17.7
c24.8,0,47.6,6.1,68.2,18.2c20.6,12.1,37,29.5,49.1,52.3c12.1,22.7,18.2,49.1,18.2,79l-0.4,11.7h-181.8
c3.6,11.4,10.5,20.7,20.9,28.1c10.3,7.3,21.3,11,33,11c14.4,0,26.3-2.2,35.7-6.5C2343.1,570.1,2352.1,563.7,2360.8,555.3z
M2244.1,486.2h92.9c-2.1-12.3-7.5-22.1-16.2-29.4s-18.7-11-30.1-11s-21.5,3.7-30.3,11C2251.7,464.1,2246.2,473.9,2244.1,486.2z"/>
<path d="M2565.9,446.3c-9.9,0-17.1,1.1-21.5,3.4c-4.5,2.2-6.7,5.9-6.7,11s3.4,8.8,10.3,11.2c6.9,2.4,18,4.9,33.2,7.6
c20,3,37,6.7,50.9,11.2s26,12.1,36.1,22.9c10.2,10.8,15.3,25.9,15.3,45.3c0,29.9-10.9,52.4-32.8,67.6
c-21.8,15.1-50.3,22.7-85.3,22.7c-25.7,0-49.5-3.7-71.4-11c-21.8-7.3-37.4-14.7-46.7-22.2l33.7-60.6c10.2,9,23.4,15.8,39.7,20.4
c16.3,4.6,31.3,7,45.1,7c19.7,0,29.6-5.2,29.6-15.7c0-5.4-3.3-9.4-9.9-11.9c-6.6-2.5-17.2-5.2-31.9-7.9c-18.9-3.3-34.9-7.2-48-11.7
c-13.2-4.5-24.6-12.2-34.3-23.1c-9.7-10.9-14.6-26-14.6-45.1c0-27.2,9.7-48.5,29-63.7c19.3-15.3,46-22.9,80.1-22.9
c23.3,0,44.4,3.6,63.3,10.8c18.9,7.2,34,14.5,45.3,22l-32.8,58.8c-10.8-7.5-23.2-13.7-37.3-18.6
C2590.5,448.7,2577.6,446.3,2565.9,446.3z"/>
<path d="M2817.3,446.3c-9.9,0-17.1,1.1-21.5,3.4c-4.5,2.2-6.7,5.9-6.7,11s3.4,8.8,10.3,11.2c6.9,2.4,18,4.9,33.2,7.6
c20,3,37,6.7,50.9,11.2s26,12.1,36.1,22.9c10.2,10.8,15.3,25.9,15.3,45.3c0,29.9-10.9,52.4-32.8,67.6
c-21.8,15.1-50.3,22.7-85.3,22.7c-25.7,0-49.5-3.7-71.4-11c-21.8-7.3-37.4-14.7-46.7-22.2l33.7-60.6c10.2,9,23.4,15.8,39.7,20.4
c16.3,4.6,31.3,7,45.1,7c19.8,0,29.6-5.2,29.6-15.7c0-5.4-3.3-9.4-9.9-11.9c-6.6-2.5-17.2-5.2-31.9-7.9c-18.9-3.3-34.9-7.2-48-11.7
c-13.2-4.5-24.6-12.2-34.3-23.1c-9.7-10.9-14.6-26-14.6-45.1c0-27.2,9.7-48.5,29-63.7c19.3-15.3,46-22.9,80.1-22.9
c23.3,0,44.4,3.6,63.3,10.8c18.9,7.2,34,14.5,45.3,22l-32.8,58.8c-10.8-7.5-23.2-13.7-37.3-18.6
C2841.8,448.7,2828.9,446.3,2817.3,446.3z"/>
<g>
<path d="M2508,724h60.2v17.3H2508V724z"/>
<path d="M2629.2,694.4c4.9-2,10.2-3.1,16-3.1c10.9,0,19.5,3.4,25.9,10.2s9.6,16.7,9.6,29.6v57.3h-19.6v-52.6
c0-9.3-1.7-16.2-5.1-20.7c-3.4-4.5-9.1-6.7-17-6.7c-6.5,0-11.8,2.4-16.1,7.1c-4.3,4.8-6.4,11.5-6.4,20.2v52.6h-19.6v-94.6h19.6v9.5
C2620.2,699.4,2624.4,696.4,2629.2,694.4z"/>
<path d="M2790.3,833.2c-8.6,6.8-19.4,10.2-32.3,10.2c-7.9,0-15.2-1.4-21.9-4.1s-12.1-6.8-16.3-12.2s-6.6-11.9-7.1-19.6h19.6
c0.7,6.1,3.5,10.8,8.4,13.9c4.9,3.2,10.7,4.8,17.4,4.8c7,0,13.1-2,18.2-6c5.1-4,7.7-10.3,7.7-18.9v-24.7c-3.6,3.4-8,6.2-13.3,8.2
c-5.2,2.1-10.7,3.1-16.3,3.1c-8.7,0-16.6-2.1-23.7-6.4c-7.1-4.3-12.6-10-16.7-17.3c-4-7.3-6-15.5-6-24.6s2-17.3,6-24.7
s9.6-13.2,16.7-17.4c7.1-4.3,15-6.4,23.7-6.4c5.7,0,11.1,1,16.3,3.1s9.6,4.8,13.3,8.2v-8.8h19.4v107.8
C2803.2,815.9,2798.9,826.4,2790.3,833.2z M2782.2,755.7c2.6-4.7,3.8-10,3.8-15.9s-1.3-11.2-3.8-16c-2.6-4.8-6.1-8.5-10.5-11.1
c-4.5-2.7-9.5-4-15.1-4c-5.8,0-10.9,1.4-15.4,4.3c-4.5,2.8-7.9,6.6-10.3,11.4c-2.4,4.8-3.6,9.9-3.6,15.5c0,5.4,1.2,10.5,3.6,15.3
c2.4,4.8,5.8,8.6,10.3,11.5s9.6,4.3,15.4,4.3c5.6,0,10.6-1.4,15.1-4.1C2776.1,764.1,2779.6,760.4,2782.2,755.7z"/>
<path d="M2843.5,788.4h-21.6l37.9-48l-36.4-46.6h22.6l25.7,33.3l25.8-33.3h21.6l-36.2,45.9l37.9,48.6h-22.6l-27.4-35L2843.5,788.4z
"/>
</g>
<path d="M835.8,319.2c-11.5-18.9-27.4-33.7-47.6-44.7c-20.2-10.9-43-16.4-68.5-16.4h-90.6c-8.6,39.6-21.3,77.2-38,112.4
c-10,21-21.3,41-33.9,59.9v209.2H647v-135h72.7c25.4,0,48.3-5.5,68.5-16.4s36.1-25.8,47.6-44.7c11.5-18.9,17.3-39.5,17.3-61.9
C853.1,358.9,847.4,338.1,835.8,319.2z M747,416.6c-9.4,9-21.8,13.5-37,13.5l-62.8,0.4v-93.4l62.8-0.4c15.3,0,27.6,4.5,37,13.5
s14.1,20,14.1,33.2C761.1,396.6,756.4,407.7,747,416.6z"/>
<path class="st0" d="M164.7,698.7c-3.5-16.5-10.4-49.6-11.3-49.6c-147.1-88-129.7-240.3-81-327.4C82.8,431.4,277,507.1,163.8,641.2
c-0.9,1.7,5.2,22.6,10.4,41.8c22.6-38.3,56.6-84.4,54.8-88.8C89.7,254.7,525,228.6,615.5,17.9c40.9,203.7-20.9,518.9-370.8,599
c-1.7,0.9-63.5,109.7-66.2,110.6c0-1.7-26.1-0.9-22.6-9.6C157.8,712.6,161.2,705.7,164.7,698.7L164.7,698.7z M160.4,616.9
c44.4-51.4-7.8-139.3-39.2-168C174.3,540.2,170.8,593.3,160.4,616.9L160.4,616.9z"/>
</svg>

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 27.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 2962.2 860.2" style="enable-background:new 0 0 2962.2 860.2;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;stroke:#000000;stroke-miterlimit:10;}
.st1{fill:#17541F;stroke:#000000;stroke-miterlimit:10;}
</style>
<path class="st0" d="M1055.6,639.7v-20.6c-18,20-43.1,30.1-75.4,30.1c-22.4,0-42.8-5.8-61-17.5c-18.3-11.7-32.5-27.8-42.9-48.3
c-10.3-20.5-15.5-43.3-15.5-68.4c0-25.1,5.2-48,15.5-68.5s24.6-36.6,42.9-48.3s38.6-17.5,61-17.5c32.3,0,57.5,10,75.4,30.1v-20.6
h85.3v249.6L1055.6,639.7L1055.6,639.7z M1059.1,514.9c0-17.4-5.2-31.9-15.5-43.8c-10.3-11.8-23.9-17.7-40.6-17.7
c-16.8,0-30.2,5.9-40.4,17.7c-10.2,11.8-15.3,26.4-15.3,43.8c0,17.4,5.1,31.9,15.3,43.8c10.2,11.8,23.6,17.7,40.4,17.7
c16.8,0,30.3-5.9,40.6-17.7C1054,546.9,1059.1,532.3,1059.1,514.9z"/>
<path class="st0" d="M1417.8,398.2c18.3,11.7,32.5,27.8,42.9,48.3c10.3,20.5,15.5,43.3,15.5,68.5c0,25.1-5.2,48-15.5,68.4
c-10.3,20.5-24.6,36.6-42.9,48.3s-38.6,17.5-61,17.5c-32.3,0-57.5-10-75.4-30.1v165.6h-85.3V390.2h85.3v20.6
c18-20,43.1-30.1,75.4-30.1C1379.2,380.7,1399.5,386.6,1417.8,398.2z M1389.5,514.9c0-17.4-5.1-31.9-15.3-43.8
c-10.2-11.8-23.6-17.7-40.4-17.7s-30.2,5.9-40.4,17.7c-10.2,11.8-15.3,26.4-15.3,43.8c0,17.4,5.1,31.9,15.3,43.8
c10.2,11.8,23.6,17.7,40.4,17.7s30.2-5.9,40.4-17.7S1389.5,532.3,1389.5,514.9z"/>
<path class="st0" d="M1713.6,555.3l53,49.4c-28.1,29.6-66.7,44.4-115.8,44.4c-28.1,0-53-5.8-74.5-17.5s-38.2-27.7-49.8-48
c-11.7-20.3-17.7-43.2-18-68.7c0-24.8,5.9-47.5,17.7-68c11.8-20.5,28.1-36.7,48.7-48.5s43.5-17.7,68.7-17.7
c24.8,0,47.6,6.1,68.2,18.2s37,29.5,49.1,52.3c12.1,22.7,18.2,49.1,18.2,79l-0.4,11.7h-181.8c3.6,11.4,10.5,20.7,20.9,28.1
c10.3,7.3,21.3,11,33,11c14.4,0,26.3-2.2,35.7-6.5C1695.8,570.1,1704.9,563.7,1713.6,555.3z M1596.9,486.2h92.9
c-2.1-12.3-7.5-22.1-16.2-29.4s-18.7-11-30.1-11s-21.5,3.7-30.3,11S1599,473.9,1596.9,486.2z"/>
<path class="st0" d="M1908.8,418.4c7.8-10.8,17.2-19,28.3-24.7s22-8.5,32.8-8.5c11.4,0,20,1.6,26,4.9l-10.8,72.7
c-8.4-2.1-15.7-3.1-22-3.1c-17.1,0-30.4,4.3-39.9,12.8c-9.6,8.5-14.4,24.2-14.4,46.9v120.3h-85.3V390.2h85.3V418.4L1908.8,418.4z"/>
<path class="st0" d="M2113,258.2v381.5h-85.3V258.2H2113z"/>
<path class="st0" d="M2360.8,555.3l53,49.4c-28.1,29.6-66.7,44.4-115.8,44.4c-28.1,0-53-5.8-74.5-17.5s-38.2-27.7-49.8-48
c-11.7-20.3-17.7-43.2-18-68.7c0-24.8,5.9-47.5,17.7-68s28.1-36.7,48.7-48.5c20.6-11.8,43.5-17.7,68.7-17.7
c24.8,0,47.6,6.1,68.2,18.2c20.6,12.1,37,29.5,49.1,52.3c12.1,22.7,18.2,49.1,18.2,79l-0.4,11.7h-181.8
c3.6,11.4,10.5,20.7,20.9,28.1c10.3,7.3,21.3,11,33,11c14.4,0,26.3-2.2,35.7-6.5C2343.1,570.1,2352.1,563.7,2360.8,555.3z
M2244.1,486.2h92.9c-2.1-12.3-7.5-22.1-16.2-29.4s-18.7-11-30.1-11s-21.5,3.7-30.3,11C2251.7,464.1,2246.2,473.9,2244.1,486.2z"/>
<path class="st0" d="M2565.9,446.3c-9.9,0-17.1,1.1-21.5,3.4c-4.5,2.2-6.7,5.9-6.7,11s3.4,8.8,10.3,11.2c6.9,2.4,18,4.9,33.2,7.6
c20,3,37,6.7,50.9,11.2s26,12.1,36.1,22.9c10.2,10.8,15.3,25.9,15.3,45.3c0,29.9-10.9,52.4-32.8,67.6
c-21.8,15.1-50.3,22.7-85.3,22.7c-25.7,0-49.5-3.7-71.4-11c-21.8-7.3-37.4-14.7-46.7-22.2l33.7-60.6c10.2,9,23.4,15.8,39.7,20.4
c16.3,4.6,31.3,7,45.1,7c19.7,0,29.6-5.2,29.6-15.7c0-5.4-3.3-9.4-9.9-11.9c-6.6-2.5-17.2-5.2-31.9-7.9c-18.9-3.3-34.9-7.2-48-11.7
c-13.2-4.5-24.6-12.2-34.3-23.1c-9.7-10.9-14.6-26-14.6-45.1c0-27.2,9.7-48.5,29-63.7c19.3-15.3,46-22.9,80.1-22.9
c23.3,0,44.4,3.6,63.3,10.8c18.9,7.2,34,14.5,45.3,22l-32.8,58.8c-10.8-7.5-23.2-13.7-37.3-18.6
C2590.5,448.7,2577.6,446.3,2565.9,446.3z"/>
<path class="st0" d="M2817.3,446.3c-9.9,0-17.1,1.1-21.5,3.4c-4.5,2.2-6.7,5.9-6.7,11s3.4,8.8,10.3,11.2c6.9,2.4,18,4.9,33.2,7.6
c20,3,37,6.7,50.9,11.2s26,12.1,36.1,22.9c10.2,10.8,15.3,25.9,15.3,45.3c0,29.9-10.9,52.4-32.8,67.6
c-21.8,15.1-50.3,22.7-85.3,22.7c-25.7,0-49.5-3.7-71.4-11c-21.8-7.3-37.4-14.7-46.7-22.2l33.7-60.6c10.2,9,23.4,15.8,39.7,20.4
c16.3,4.6,31.3,7,45.1,7c19.8,0,29.6-5.2,29.6-15.7c0-5.4-3.3-9.4-9.9-11.9c-6.6-2.5-17.2-5.2-31.9-7.9c-18.9-3.3-34.9-7.2-48-11.7
c-13.2-4.5-24.6-12.2-34.3-23.1c-9.7-10.9-14.6-26-14.6-45.1c0-27.2,9.7-48.5,29-63.7c19.3-15.3,46-22.9,80.1-22.9
c23.3,0,44.4,3.6,63.3,10.8c18.9,7.2,34,14.5,45.3,22l-32.8,58.8c-10.8-7.5-23.2-13.7-37.3-18.6
C2841.8,448.7,2828.9,446.3,2817.3,446.3z"/>
<g>
<path class="st0" d="M2508,724h60.2v17.3H2508V724z"/>
<path class="st0" d="M2629.2,694.4c4.9-2,10.2-3.1,16-3.1c10.9,0,19.5,3.4,25.9,10.2s9.6,16.7,9.6,29.6v57.3h-19.6v-52.6
c0-9.3-1.7-16.2-5.1-20.7c-3.4-4.5-9.1-6.7-17-6.7c-6.5,0-11.8,2.4-16.1,7.1c-4.3,4.8-6.4,11.5-6.4,20.2v52.6h-19.6v-94.6h19.6v9.5
C2620.2,699.4,2624.4,696.4,2629.2,694.4z"/>
<path class="st0" d="M2790.3,833.2c-8.6,6.8-19.4,10.2-32.3,10.2c-7.9,0-15.2-1.4-21.9-4.1s-12.1-6.8-16.3-12.2s-6.6-11.9-7.1-19.6
h19.6c0.7,6.1,3.5,10.8,8.4,13.9c4.9,3.2,10.7,4.8,17.4,4.8c7,0,13.1-2,18.2-6c5.1-4,7.7-10.3,7.7-18.9v-24.7
c-3.6,3.4-8,6.2-13.3,8.2c-5.2,2.1-10.7,3.1-16.3,3.1c-8.7,0-16.6-2.1-23.7-6.4c-7.1-4.3-12.6-10-16.7-17.3c-4-7.3-6-15.5-6-24.6
s2-17.3,6-24.7s9.6-13.2,16.7-17.4c7.1-4.3,15-6.4,23.7-6.4c5.7,0,11.1,1,16.3,3.1s9.6,4.8,13.3,8.2v-8.8h19.4v107.8
C2803.2,815.9,2798.9,826.4,2790.3,833.2z M2782.2,755.7c2.6-4.7,3.8-10,3.8-15.9s-1.3-11.2-3.8-16c-2.6-4.8-6.1-8.5-10.5-11.1
c-4.5-2.7-9.5-4-15.1-4c-5.8,0-10.9,1.4-15.4,4.3c-4.5,2.8-7.9,6.6-10.3,11.4c-2.4,4.8-3.6,9.9-3.6,15.5c0,5.4,1.2,10.5,3.6,15.3
c2.4,4.8,5.8,8.6,10.3,11.5s9.6,4.3,15.4,4.3c5.6,0,10.6-1.4,15.1-4.1C2776.1,764.1,2779.6,760.4,2782.2,755.7z"/>
<path class="st0" d="M2843.5,788.4h-21.6l37.9-48l-36.4-46.6h22.6l25.7,33.3l25.8-33.3h21.6l-36.2,45.9l37.9,48.6h-22.6l-27.4-35
L2843.5,788.4z"/>
</g>
<path class="st0" d="M835.8,319.2c-11.5-18.9-27.4-33.7-47.6-44.7c-20.2-10.9-43-16.4-68.5-16.4h-90.6c-8.6,39.6-21.3,77.2-38,112.4
c-10,21-21.3,41-33.9,59.9v209.2H647v-135h72.7c25.4,0,48.3-5.5,68.5-16.4s36.1-25.8,47.6-44.7c11.5-18.9,17.3-39.5,17.3-61.9
C853.1,358.9,847.4,338.1,835.8,319.2z M747,416.6c-9.4,9-21.8,13.5-37,13.5l-62.8,0.4v-93.4l62.8-0.4c15.3,0,27.6,4.5,37,13.5
s14.1,20,14.1,33.2C761.1,396.6,756.4,407.7,747,416.6z"/>
<path class="st1" d="M164.7,698.7c-3.5-16.5-10.4-49.6-11.3-49.6c-147.1-88-129.7-240.3-81-327.4C82.8,431.4,277,507.1,163.8,641.2
c-0.9,1.7,5.2,22.6,10.4,41.8c22.6-38.3,56.6-84.4,54.8-88.8C89.7,254.7,525,228.6,615.5,17.9c40.9,203.7-20.9,518.9-370.8,599
c-1.7,0.9-63.5,109.7-66.2,110.6c0-1.7-26.1-0.9-22.6-9.6C157.8,712.6,161.2,705.7,164.7,698.7L164.7,698.7z M160.4,616.9
c44.4-51.4-7.8-139.3-39.2-168C174.3,540.2,170.8,593.3,160.4,616.9L160.4,616.9z"/>
</svg>

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 67 KiB

View File

Before

Width:  |  Height:  |  Size: 661 KiB

After

Width:  |  Height:  |  Size: 661 KiB

View File

Before

Width:  |  Height:  |  Size: 457 KiB

After

Width:  |  Height:  |  Size: 457 KiB

View File

Before

Width:  |  Height:  |  Size: 436 KiB

After

Width:  |  Height:  |  Size: 436 KiB

View File

Before

Width:  |  Height:  |  Size: 462 KiB

After

Width:  |  Height:  |  Size: 462 KiB

View File

Before

Width:  |  Height:  |  Size: 608 KiB

After

Width:  |  Height:  |  Size: 608 KiB

View File

Before

Width:  |  Height:  |  Size: 698 KiB

After

Width:  |  Height:  |  Size: 698 KiB

View File

Before

Width:  |  Height:  |  Size: 706 KiB

After

Width:  |  Height:  |  Size: 706 KiB

View File

Before

Width:  |  Height:  |  Size: 480 KiB

After

Width:  |  Height:  |  Size: 480 KiB

View File

Before

Width:  |  Height:  |  Size: 680 KiB

After

Width:  |  Height:  |  Size: 680 KiB

View File

Before

Width:  |  Height:  |  Size: 686 KiB

After

Width:  |  Height:  |  Size: 686 KiB

View File

Before

Width:  |  Height:  |  Size: 848 KiB

After

Width:  |  Height:  |  Size: 848 KiB

View File

Before

Width:  |  Height:  |  Size: 703 KiB

After

Width:  |  Height:  |  Size: 703 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

View File

Before

Width:  |  Height:  |  Size: 388 KiB

After

Width:  |  Height:  |  Size: 388 KiB

View File

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

View File

Before

Width:  |  Height:  |  Size: 517 KiB

After

Width:  |  Height:  |  Size: 517 KiB

View File

@ -577,7 +577,7 @@
- Allow setting more than one tag in mail rules
[\@jonasc](https://github.com/jonasc) ([\#270](https://github.com/paperless-ngx/paperless-ngx/pull/270))
- Global drag\'n\'drop [\@shamoon](https://github.com/shamoon)
- Global drag'n'drop [\@shamoon](https://github.com/shamoon)
([\#283](https://github.com/paperless-ngx/paperless-ngx/pull/283))
- Fix: download buttons should disable while waiting
[\@shamoon](https://github.com/shamoon) ([\#630](https://github.com/paperless-ngx/paperless-ngx/pull/630))
@ -607,7 +607,7 @@
### Bug Fixes
- Add \"localhost\" to ALLOWED_HOSTS
- Add "localhost" to ALLOWED_HOSTS
[\@gador](https://github.com/gador) ([\#700](https://github.com/paperless-ngx/paperless-ngx/pull/700))
- Fix: scanners table [\@qcasey](https://github.com/qcasey) ([\#690](https://github.com/paperless-ngx/paperless-ngx/pull/690))
- Adds wait for file before consuming
@ -644,7 +644,7 @@
([\#393](https://github.com/paperless-ngx/paperless-ngx/pull/393))
- Fix filterable dropdown buttons arent translated
[\@shamoon](https://github.com/shamoon) ([\#366](https://github.com/paperless-ngx/paperless-ngx/pull/366))
- Fix 224: \"Auto-detected date is day before receipt date\"
- Fix 224: "Auto-detected date is day before receipt date"
[\@a17t](https://github.com/a17t) ([\#246](https://github.com/paperless-ngx/paperless-ngx/pull/246))
- Fix minor sphinx errors [\@shamoon](https://github.com/shamoon)
([\#322](https://github.com/paperless-ngx/paperless-ngx/pull/322))
@ -706,7 +706,7 @@ This is the first release of the revived paperless-ngx project 🎉. Thank
you to everyone on the paperless-ngx team for your initiative and
excellent teamwork!
Version 1.6.0 merges several pending PRs from jonaswinkler\'s repo and
Version 1.6.0 merges several pending PRs from jonaswinkler's repo and
includes new feature updates and bug fixes. Major backend and UI changes
include:
@ -726,14 +726,14 @@ include:
when document list is reloading ([jonaswinkler\#1297](https://github.com/jonaswinkler/paperless-ng/pull/1297)).
- [\@shamoon](https://github.com/shamoon) improved the PDF viewer on
mobile ([\#2](https://github.com/paperless-ngx/paperless-ngx/pull/2)).
- [\@shamoon](https://github.com/shamoon) added \'any\' / \'all\' and
\'not\' filtering with tags ([\#10](https://github.com/paperless-ngx/paperless-ngx/pull/10)).
- [\@shamoon](https://github.com/shamoon) added 'any' / 'all' and
'not' filtering with tags ([\#10](https://github.com/paperless-ngx/paperless-ngx/pull/10)).
- [\@shamoon](https://github.com/shamoon) added warnings for unsaved
changes, with smart edit buttons ([\#13](https://github.com/paperless-ngx/paperless-ngx/pull/13)).
- [\@benjaminfrank](https://github.com/benjaminfrank) enabled a
non-root access to port 80 via systemd ([\#18](https://github.com/paperless-ngx/paperless-ngx/pull/18)).
- [\@tribut](https://github.com/tribut) added simple \"delete to
trash\" functionality ([\#24](https://github.com/paperless-ngx/paperless-ngx/pull/24)). See `PAPERLESS_TRASH_DIR`.
- [\@tribut](https://github.com/tribut) added simple "delete to
trash" functionality ([\#24](https://github.com/paperless-ngx/paperless-ngx/pull/24)). See `PAPERLESS_TRASH_DIR`.
- [\@amenk](https://github.com/amenk) fixed the search box overlay
menu on mobile ([\#32](https://github.com/paperless-ngx/paperless-ngx/pull/32)).
- [\@dblitt](https://github.com/dblitt) updated the login form to not
@ -909,26 +909,22 @@ This is a maintenance release.
- Changes
- Firefox only: Highlight search query in PDF previews.
- New URL pattern for accessing documents by ASN directly
(<http://>\<paperless\>/asn/123)
(<http://><paperless>/asn/123)
- Added logging when executing pre\* and post-consume scripts.
- Better error logging during document consumption.
- Updated python dependencies.
- Automatically inserts typed text when opening \"Create new\"
- Automatically inserts typed text when opening "Create new"
dialogs on the document details page.
- Fixes
- Fixed an issue with null characters in the document content.
::: {.note}
::: {.title}
Note
:::
!!! note
The changed to the full text searching require you to reindex your
documents. _The docker image does this automatically, you don\'t need to
documents. _The docker image does this automatically, you don't need to
do anything._ To do this, execute the `document_index reindex`
management command (see `administration-index`{.interpreted-text
role="ref"}).
:::
### paperless-ng 1.3.2
@ -1031,7 +1027,7 @@ This release contains new database migrations.
worker processes of the web server. See
`configuration-docker`{.interpreted-text role="ref"}.
- Some more memory usage optimizations.
- Don\'t show inbox statistics if no inbox tag is defined.
- Don't show inbox statistics if no inbox tag is defined.
### paperless-ng 1.1.2
@ -1051,8 +1047,8 @@ This release contains new database migrations.
This release contains new database migrations.
- Fixed a bug in the sanity checker that would cause it to display \"x
not in list\" errors instead of actual issues.
- Fixed a bug in the sanity checker that would cause it to display "x
not in list" errors instead of actual issues.
- Fixed a bug with filename generation for archive filenames that
would cause the archive files of two documents to overlap.
- This happened when `PAPERLESS_FILENAME_FORMAT` is used and the
@ -1061,8 +1057,8 @@ This release contains new database migrations.
- Paperless will now store the archive filename in the database as
well instead of deriving it from the original filename, and use
the same logic for detecting and avoiding filename clashes
that\'s also used for original filenames.
- The migrations will repair any missing archive files. If you\'re
that's also used for original filenames.
- The migrations will repair any missing archive files. If you're
using tika, ensure that tika is running while performing the
migration. Docker-compose will take care of that.
- Fixed a bug with thumbnail regeneration when TIKA integration was
@ -1070,8 +1066,8 @@ This release contains new database migrations.
- Added ASN as a placeholder field to the filename format.
- The docker image now comes with built-in shortcuts for most
management commands. These are now the recommended way to execute
management commands, since these also ensure that they\'re always
executed as the paperless user and you\'re less likely to run into
management commands, since these also ensure that they're always
executed as the paperless user and you're less likely to run into
permission issues. See
`utilities-management-commands`{.interpreted-text role="ref"}.
@ -1093,10 +1089,7 @@ This release contains new database migrations.
- Live updates to document lists and saved views when new documents
are added.
::: {.hint}
::: {.title}
Hint
:::
!!! tip
For status notifications and live updates to work, paperless now
requires an [ASGI](https://asgi.readthedocs.io/en/latest/)-enabled
@ -1119,7 +1112,6 @@ This release contains new database migrations.
Apache `mod_wsgi` users, see
`this note <faq-mod_wsgi>`{.interpreted-text role="ref"}.
:::
- Paperless now offers suggestions for tags, correspondents and types
on the document detail page.
@ -1143,8 +1135,8 @@ This release contains new database migrations.
- Better icon for document previews.
- Better info section in the side bar.
- Paperless no longer logs to the database. Instead, logs are
written to rotating log files. This solves many \"database is
locked\" issues on Raspberry Pi, especially when SQLite is used.
written to rotating log files. This solves many "database is
locked" issues on Raspberry Pi, especially when SQLite is used.
- By default, log files are written to `PAPERLESS_DATA_DIR/log/`.
Logging settings can be adjusted with `PAPERLESS_LOGGING_DIR`,
`PAPERLESS_LOGROTATE_MAX_SIZE` and
@ -1173,7 +1165,7 @@ bug reports coming in, I think that this is reasonably stable.
- Range selection with shift clicking is now possible in the
document list.
- Filtering correspondent, type and tag management pages by name.
- Focus \"Name\" field in dialogs by default.
- Focus "Name" field in dialogs by default.
### paperless-ng 0.9.14
@ -1235,8 +1227,8 @@ paperless.
- Fixed an issue with filenames of downloaded files: Dates where
off by one day due to timezone issues.
- Searching will continue to work even when the index returns
non-existing documents. This resulted in \"Document does not
exist\" errors before. Instead, a warning is logged, indicating
non-existing documents. This resulted in "Document does not
exist" errors before. Instead, a warning is logged, indicating
the issue.
- An issue with the consumer crashing when invalid regular
expression were used was fixed.
@ -1277,11 +1269,11 @@ paperless.
new ASN to a document.
- Form field validation: When providing invalid input in a form
(such as a duplicate ASN or no name), paperless now has visual
indicators and clearer error messages about what\'s wrong.
indicators and clearer error messages about what's wrong.
- Paperless disables buttons with network actions (such as save
and delete) when a network action is active. This indicates that
something is happening and prevents double clicking.
- When using \"Save & next\", the title field is focussed
- When using "Save & next", the title field is focussed
automatically to better support keyboard editing.
- E-Mail: Added filter rule parameters to allow inline attachments
(watch out for mails with inlined images!) and attachment
@ -1290,11 +1282,11 @@ paperless.
Shamoon](https://github.com/shamoon). This is useful for hiding
Paperless behind single sign on applications such as
[authelia](https://www.authelia.com/).
- \"Clear filters\" has been renamed to \"Reset filters\" and now
- "Clear filters" has been renamed to "Reset filters" and now
correctly restores the default filters on saved views. Thanks to
[Michael Shamoon](https://github.com/shamoon)
- Fixes
- Paperless was unable to save views when \"Not assigned\" was
- Paperless was unable to save views when "Not assigned" was
chosen in one of the filter dropdowns.
- Clearer error messages when pre and post consumption scripts do
not exist.
@ -1310,7 +1302,7 @@ paperless.
### paperless-ng 0.9.10
- Bulk editing
- Thanks to [Michael Shamoon](https://github.com/shamoon), we\'ve
- Thanks to [Michael Shamoon](https://github.com/shamoon), we've
got a new interface for the bulk editor.
- There are some configuration options in the settings to alter
the behavior.
@ -1319,7 +1311,7 @@ paperless.
publishes a webmanifest, which is useful for adding the
application to home screens on mobile devices.
- The Paperless-ng logo now navigates to the dashboard.
- Filter for documents that don\'t have any correspondents, types
- Filter for documents that don't have any correspondents, types
or tags assigned.
- Tags, types and correspondents are now sorted case insensitive.
- Lots of preparation work for localization support.
@ -1333,10 +1325,7 @@ paperless.
- The consumer used to stop working when encountering an
incomplete classifier model file.
::: {.note}
::: {.title}
Note
:::
!!! note
The bulk delete operations did not update the search index. Therefore,
documents that you deleted remained in the index and caused the search
@ -1347,7 +1336,6 @@ However, this change is not retroactive: If you used the delete method
of the bulk editor, you need to reindex your search index by
`running the management command document_index with the argument reindex <administration-index>`{.interpreted-text
role="ref"}.
:::
### paperless-ng 0.9.9
@ -1358,18 +1346,18 @@ Christmas release!
- The following operations are available: Add and remove
correspondents, tags, document types from selected documents, as
well as mass-deleting documents.
- We\'ve got a more fancy UI in the works that makes these
features more accessible, but that\'s not quite ready yet.
- We've got a more fancy UI in the works that makes these
features more accessible, but that's not quite ready yet.
- Searching
- Paperless now supports searching for similar documents (\"More
like this\") both from the document detail page as well as from
- Paperless now supports searching for similar documents ("More
like this") both from the document detail page as well as from
individual search results.
- A search score indicates how well a document matches the search
query, or how similar a document is to a given reference
document.
- Other additions and changes
- Clarification in the UI that the fields \"Match\" and \"Is
insensitive\" are not relevant for the Auto matching algorithm.
- Clarification in the UI that the fields "Match" and "Is
insensitive" are not relevant for the Auto matching algorithm.
- New select interface for tags, types and correspondents allows
filtering. This also improves tag selection. Thanks again to
[Michael Shamoon](https://github.com/shamoon)!
@ -1450,11 +1438,11 @@ This release focusses primarily on many small issues with the UI.
- Paperless now has proper window titles.
- Fixed an issue with the small cards when more than 7 tags were
used.
- Navigation of the \"Show all\" links adjusted. They navigate to
- Navigation of the "Show all" links adjusted. They navigate to
the saved view now, if available in the sidebar.
- Some indication on the document lists that a filter is active
was added.
- There\'s a new filter to filter for documents that do _not_ have
- There's a new filter to filter for documents that do _not_ have
a certain tag.
- The file upload box now shows upload progress.
- The document edit page was reorganized.
@ -1479,15 +1467,11 @@ This release focusses primarily on many small issues with the UI.
filenames anymore. It will rather append `_01`, `_02`, etc when
it detects duplicate filenames.
::: {.note}
::: {.title}
Note
:::
!!! note
The changes to the filename format will apply to newly added documents
and changed documents. If you want all files to reflect these changes,
execute the `document_renamer` management command.
:::
### paperless-ng 0.9.5
@ -1570,7 +1554,7 @@ primarily.
need to do this once, since the schema of the search index
changed. Paperless keeps the index updated after that whenever
something changes.
- Paperless now has spelling corrections (\"Did you mean\") for
- Paperless now has spelling corrections ("Did you mean") for
miss-typed queries.
- The documentation contains
`information about the query syntax <basic-searching>`{.interpreted-text
@ -1640,7 +1624,7 @@ primarily.
role="ref"} This features will most likely be removed in future
versions.
- **Added:** New frontend. Features:
- Single page application: It\'s much more responsive than the
- Single page application: It's much more responsive than the
django admin pages.
- Dashboard. Shows recently scanned documents, or todo notes, or
other documents at wish. Allows uploading of documents. Shows
@ -1662,7 +1646,7 @@ primarily.
- **Added:** Archive serial numbers. Assign these to quickly find
documents stored in physical binders.
- **Added:** Enabled the internal user management of django. This
isn\'t really a multi user solution, however, it allows more than
isn't really a multi user solution, however, it allows more than
one user to access the website and set some basic permissions /
renew passwords.
- **Modified \[breaking\]:** All new mail consumer with customizable
@ -1717,7 +1701,7 @@ primarily.
- **Settings:**
- `PAPERLESS_FORGIVING_OCR` is now default and gone. Reason: Even
if `langdetect` fails to detect a language, tesseract still does
a very good job at ocr\'ing a document with the default
a very good job at ocr'ing a document with the default
language. Certain language specifics such as umlauts may not get
picked up properly.
- `PAPERLESS_DEBUG` defaults to `false`.
@ -1798,34 +1782,34 @@ primarily.
[\#442](https://github.com/the-paperless-project/paperless/pull/442).
- Added a `.editorconfig` file to better specify coding style.
- [Joshua Taillon](https://github.com/jat255) also added some logic to
tie Paperless\' date guessing logic into how it parses file names on
tie Paperless' date guessing logic into how it parses file names on
import.
[\#440](https://github.com/the-paperless-project/paperless/pull/440)
### 2.5.0
- **New dependency**: Paperless now optimises thumbnail generation
with [optipng](http://optipng.sourceforge.net/), so you\'ll need to
with [optipng](http://optipng.sourceforge.net/), so you'll need to
install that somewhere in your PATH or declare its location in
`PAPERLESS_OPTIPNG_BINARY`. The Docker image has already been
updated on the Docker Hub, so you just need to pull the latest one
from there if you\'re a Docker user.
- \"Login free\" instances of Paperless were breaking whenever you
from there if you're a Docker user.
- "Login free" instances of Paperless were breaking whenever you
tried to edit objects in the admin: adding/deleting tags or
correspondents, or even fixing spelling. This was due to the \"user
hack\" we were applying to sessions that weren\'t using a login, as
that hack user didn\'t have a valid id. The fix was to attribute the
correspondents, or even fixing spelling. This was due to the "user
hack" we were applying to sessions that weren't using a login, as
that hack user didn't have a valid id. The fix was to attribute the
first user id in the system to this hack user.
[\#394](https://github.com/the-paperless-project/paperless/issues/394)
- A problem in how we handle slug values on Tags and Correspondents
required a few changes to how we handle this field
[\#393](https://github.com/the-paperless-project/paperless/issues/393):
1. Slugs are no longer editable. They\'re derived from the name of
1. Slugs are no longer editable. They're derived from the name of
the tag or correspondent at save time, so if you wanna change
the slug, you have to change the name, and even then you\'re
the slug, you have to change the name, and even then you're
restricted to the rules of the `slugify()` function. The slug
value is still visible in the admin though.
2. I\'ve added a migration to go over all existing tags &
2. I've added a migration to go over all existing tags &
correspondents and rewrite the `.slug` values to ones conforming
to the `slugify()` rules.
3. The consumption process now uses the same rules as `.save()` in
@ -1836,7 +1820,7 @@ primarily.
Thanks to [Andrew Peng](https://github.com/pengc99) for reporting
this.
[\#414](https://github.com/the-paperless-project/paperless/issues/414).
- A bug in the Dockerfile meant that Tesseract language files weren\'t
- A bug in the Dockerfile meant that Tesseract language files weren't
being installed correctly. [euri10](https://github.com/euri10) was
quick to provide a fix:
[\#406](https://github.com/the-paperless-project/paperless/issues/406),
@ -1851,13 +1835,13 @@ primarily.
### 2.4.0
- A new set of actions are now available thanks to
[jonaswinkler](https://github.com/jonaswinkler)\'s very first pull
[jonaswinkler](https://github.com/jonaswinkler)'s very first pull
request! You can now do nifty things like tag documents in bulk, or
set correspondents in bulk.
[\#405](https://github.com/the-paperless-project/paperless/pull/405)
- The import/export system is now a little smarter. By default,
documents are tagged as `unencrypted`, since exports are by their
nature unencrypted. It\'s now in the import step that we decide the
nature unencrypted. It's now in the import step that we decide the
storage type. This allows you to export from an encrypted system and
import into an unencrypted one, or vice-versa.
- The migration history has been slightly modified to accommodate
@ -1875,7 +1859,7 @@ primarily.
- Support for consuming plain text & markdown documents was added by
[Joshua Taillon](https://github.com/jat255)! This was a
long-requested feature, and it\'s addition is likely to be greatly
long-requested feature, and it's addition is likely to be greatly
appreciated by the community:
[\#395](https://github.com/the-paperless-project/paperless/pull/395)
Thanks also to [David Martin](https://github.com/ddddavidmartin) for
@ -1916,7 +1900,7 @@ primarily.
lots of different tags:
[\#391](https://github.com/the-paperless-project/paperless/pull/391).
- [Kilian Koeltzsch](https://github.com/kiliankoe) noticed a bug in
how we capture & automatically create tags, so that\'s fixed now
how we capture & automatically create tags, so that's fixed now
too:
[\#384](https://github.com/the-paperless-project/paperless/issues/384).
- [erikarvstedt](https://github.com/erikarvstedt) tweaked the
@ -1932,7 +1916,7 @@ primarily.
- [Enno Lohmeier](https://github.com/elohmeier) added three simple
features that make Paperless a lot more user (and developer)
friendly:
1. There\'s a new search box on the front page:
1. There's a new search box on the front page:
[\#374](https://github.com/the-paperless-project/paperless/pull/374).
2. The correspondents & tags pages now have a column showing the
number of relevant documents:
@ -1942,18 +1926,18 @@ primarily.
environment:
[\#376](https://github.com/the-paperless-project/paperless/pull/376).
- You now also have the ability to customise the interface to your
heart\'s content by creating a file called `overrides.css` and/or
heart's content by creating a file called `overrides.css` and/or
`overrides.js` in the root of your media directory. Thanks to [Mark
McFate](https://github.com/SummittDweller) for this idea:
[\#371](https://github.com/the-paperless-project/paperless/issues/371)
### 2.0.0
This is a big release as we\'ve changed a core-functionality of
This is a big release as we've changed a core-functionality of
Paperless: we no longer encrypt files with GPG by default.
The reasons for this are many, but it boils down to that the encryption
wasn\'t really all that useful, as files on-disk were still accessible
wasn't really all that useful, as files on-disk were still accessible
so long as you had the key, and the key was most typically stored in the
config file. In other words, your files are only as safe as the
`paperless` user is. In addition to that, _the contents of the documents
@ -1965,7 +1949,7 @@ explicitly set a passphrase in your config file.
### Migrating from 1.x
Encryption isn\'t gone, it\'s just off for new users. So long as you
Encryption isn't gone, it's just off for new users. So long as you
have `PAPERLESS_PASSPHRASE` set in your config or your environment,
Paperless should continue to operate as it always has. If however, you
want to drop encryption too, you only need to do two things:
@ -1995,7 +1979,7 @@ this big change.
for more information.
- Refactor the use of travis/tox/pytest/coverage into two files:
`.travis.yml` and `setup.cfg`.
- Start generating requirements.txt from a Pipfile. I\'ll probably
- Start generating requirements.txt from a Pipfile. I'll probably
switch over to just using pipenv in the future.
- All for a alternative FreeBSD-friendly location for
`paperless.conf`. Thanks to [Martin
@ -2015,7 +1999,7 @@ this big change.
[\#253](https://github.com/the-paperless-project/paperless/issues/253)
and
[\#323](https://github.com/the-paperless-project/paperless/issues/323),
we\'ve removed a few of the hardcoded URL values to make it easier
we've removed a few of the hardcoded URL values to make it easier
for people to host Paperless on a subdirectory. Thanks to [Quentin
Dawans](https://github.com/ovv) and [Kyle
Lucy](https://github.com/kmlucy) for helping to work this out.
@ -2028,7 +2012,7 @@ this big change.
very creating Bash skills:
[\#352](https://github.com/the-paperless-project/paperless/pull/352).
- You can now use the search field to find documents by tag thanks to
[thinkjk](https://github.com/thinkjk)\'s _first ever issue_:
[thinkjk](https://github.com/thinkjk)'s _first ever issue_:
[\#354](https://github.com/the-paperless-project/paperless/issues/354).
- Inotify is now being used to detect additions to the consume
directory thanks to some excellent work from
@ -2037,7 +2021,7 @@ this big change.
### 1.3.0
- You can now run Paperless without a login, though you\'ll still have
- You can now run Paperless without a login, though you'll still have
to create at least one user. This is thanks to a pull-request from
[matthewmoto](https://github.com/matthewmoto):
[\#295](https://github.com/the-paperless-project/paperless/pull/295).
@ -2068,7 +2052,7 @@ this big change.
[\#312](https://github.com/the-paperless-project/paperless/pull/312)
to fix
[\#306](https://github.com/the-paperless-project/paperless/issues/306).
- Patch the historical migrations to support MySQL\'s um,
- Patch the historical migrations to support MySQL's um,
_interesting_ way of handing indexes
([\#308](https://github.com/the-paperless-project/paperless/issues/308)).
Thanks to [Simon Taddiken](https://github.com/skuzzle) for reporting
@ -2090,7 +2074,7 @@ this big change.
already contains text. This can be overridden by setting
`PAPERLESS_OCR_ALWAYS=YES` either in your `paperless.conf` or in the
environment. Note that this also means that Paperless now requires
`libpoppler-cpp-dev` to be installed. **Important**: You\'ll need to
`libpoppler-cpp-dev` to be installed. **Important**: You'll need to
run `pip install -r requirements.txt` after the usual `git pull` to
properly update.
- [BastianPoe](https://github.com/BastianPoe) has also contributed a
@ -2117,7 +2101,7 @@ this big change.
### 1.0.0
- Upgrade to Django 1.11. **You\'ll need to run \`\`pip install -r
- Upgrade to Django 1.11. **You'll need to run \`\`pip install -r
requirements.txt\`\` after the usual \`\`git pull\`\` to properly
update**.
- Replace the templatetag-based hack we had for document listing in
@ -2138,14 +2122,14 @@ this big change.
[Pit](https://github.com/pitkley) on
[\#268](https://github.com/the-paperless-project/paperless/pull/268).
- Date fields in the admin are now expressed as HTML5 date fields
thanks to [Lukas Winkler](https://github.com/Findus23)\'s issue
thanks to [Lukas Winkler](https://github.com/Findus23)'s issue
[\#278](https://github.com/the-paperless-project/paperless/issues/248)
### 0.8.0
- Paperless can now run in a subdirectory on a host (`/paperless`),
rather than always running in the root (`/`) thanks to
[maphy-psd](https://github.com/maphy-psd)\'s work on
[maphy-psd](https://github.com/maphy-psd)'s work on
[\#255](https://github.com/the-paperless-project/paperless/pull/255).
### 0.7.0
@ -2154,14 +2138,14 @@ this big change.
[\#235](https://github.com/the-paperless-project/paperless/issues/235),
Paperless will no longer automatically delete documents attached to
correspondents when those correspondents are themselves deleted.
This was Django\'s default behaviour, but didn\'t make much sense in
Paperless\' case. Thanks to [Thomas
This was Django's default behaviour, but didn't make much sense in
Paperless' case. Thanks to [Thomas
Brueggemann](https://github.com/thomasbrueggemann) and [David
Martin](https://github.com/ddddavidmartin) for their input on this
one.
- Fix for
[\#232](https://github.com/the-paperless-project/paperless/issues/232)
wherein Paperless wasn\'t recognising `.tif` files properly. Thanks
wherein Paperless wasn't recognising `.tif` files properly. Thanks
to [ayounggun](https://github.com/ayounggun) for reporting this one
and to [Kusti Skytén](https://github.com/kskyten) for posting the
correct solution in the Github issue.
@ -2172,12 +2156,12 @@ this big change.
favour of BasicAuth or Django session.
- Fix the POST API so it actually works.
[\#236](https://github.com/the-paperless-project/paperless/issues/236)
- **Breaking change**: We\'ve dropped the use of
- **Breaking change**: We've dropped the use of
`PAPERLESS_SHARED_SECRET` as it was being used both for the API (now
replaced with a normal auth) and form email polling. Now that we\'re
replaced with a normal auth) and form email polling. Now that we're
only using it for email, this variable has been renamed to
`PAPERLESS_EMAIL_SECRET`. The old value will still work for a while,
but you should change your config if you\'ve been using the email
but you should change your config if you've been using the email
polling feature. Thanks to [Joshua
Gilman](https://github.com/jmgilman) for all the help with this
feature.
@ -2185,7 +2169,7 @@ this big change.
### 0.5.0
- Support for fuzzy matching in the auto-tagger & auto-correspondent
systems thanks to [Jake Gysland](https://github.com/jgysland)\'s
systems thanks to [Jake Gysland](https://github.com/jgysland)'s
patch
[\#220](https://github.com/the-paperless-project/paperless/pull/220).
- Modified the Dockerfile to prepare an export directory
@ -2214,7 +2198,7 @@ this big change.
- Fix for
[\#206](https://github.com/the-paperless-project/paperless/issues/206)
wherein the pluggable parser didn\'t recognise files with all-caps
wherein the pluggable parser didn't recognise files with all-caps
suffixes like `.PDF`
### 0.4.0
@ -2224,7 +2208,7 @@ this big change.
for more information, but the short explanation is that you can now
attach simple notes & times to documents which are made available
via the API. Currently, the default API (basically just the Django
admin) doesn\'t really make use of this, but [Thomas
admin) doesn't really make use of this, but [Thomas
Brueggemann](https://github.com/thomasbrueggemann) over at
[Paperless
Desktop](https://github.com/thomasbrueggemann/paperless-desktop) has
@ -2234,16 +2218,16 @@ this big change.
- Fix for
[\#200](https://github.com/the-paperless-project/paperless/issues/200)
(!!) where the API wasn\'t configured to allow updating the
(!!) where the API wasn't configured to allow updating the
correspondent or the tags for a document.
- The `content` field is now optional, to allow for the edge case of a
purely graphical document.
- You can no longer add documents via the admin. This never worked in
the first place, so all I\'ve done here is remove the link to the
the first place, so all I've done here is remove the link to the
broken form.
- The consumer code has been heavily refactored to support a pluggable
interface. Install a paperless consumer via pip and tell paperless
about it with an environment variable, and you\'re good to go.
about it with an environment variable, and you're good to go.
Proper documentation is on its way.
### 0.3.5
@ -2264,10 +2248,10 @@ this big change.
- Removal of django-suit due to a licensing conflict I bumped into in
0.3.3. Note that you _can_ use Django Suit with Paperless, but only
in a non-profit situation as their free license prohibits for-profit
use. As a result, I can\'t bundle Suit with Paperless without
use. As a result, I can't bundle Suit with Paperless without
conflicting with the GPL. Further development will be done against
the stock Django admin.
- I shrunk the thumbnails a little \'cause they were too big for me,
- I shrunk the thumbnails a little 'cause they were too big for me,
even on my high-DPI monitor.
- BasicAuth support for document and thumbnail downloads, as well as
the Push API thanks to \@thomasbrueggemann. See
@ -2294,14 +2278,14 @@ this big change.
### 0.3.0
- Updated to using django-filter 1.x
- Added some system checks so new users aren\'t confused by
- Added some system checks so new users aren't confused by
misconfigurations.
- Consumer loop time is now configurable for systems with slow writes.
Just set `PAPERLESS_CONSUMER_LOOP_TIME` to a number of seconds. The
default is 10.
- As per
[\#44](https://github.com/the-paperless-project/paperless/issues/44),
we\'ve removed support for `PAPERLESS_CONVERT`, `PAPERLESS_CONSUME`,
we've removed support for `PAPERLESS_CONVERT`, `PAPERLESS_CONSUME`,
and `PAPERLESS_SECRET`. Please use `PAPERLESS_CONVERT_BINARY`,
`PAPERLESS_CONSUMPTION_DIR`, and `PAPERLESS_SHARED_SECRET`
respectively instead.
@ -2316,17 +2300,17 @@ this big change.
- [\#146](https://github.com/the-paperless-project/paperless/issues/146):
Fixed a bug that allowed unauthorised access to the `/fetch` URL.
- [\#131](https://github.com/the-paperless-project/paperless/issues/131):
Document files are now automatically removed from disk when they\'re
Document files are now automatically removed from disk when they're
deleted in Paperless.
- [\#121](https://github.com/the-paperless-project/paperless/issues/121):
Fixed a bug where Paperless wasn\'t setting document creation time
Fixed a bug where Paperless wasn't setting document creation time
based on the file naming scheme.
- [\#81](https://github.com/the-paperless-project/paperless/issues/81):
Added a hook to run an arbitrary script after every document is
consumed.
- [\#98](https://github.com/the-paperless-project/paperless/issues/98):
Added optional environment variables for ImageMagick so that it
doesn\'t explode when handling Very Large Documents or when it\'s
doesn't explode when handling Very Large Documents or when it's
just running on a low-memory system. Thanks to [Florian
Harr](https://github.com/evils) for his help on this one.
- [\#89](https://github.com/the-paperless-project/paperless/issues/89)
@ -2345,8 +2329,8 @@ this big change.
### 0.1.1
- Potentially **Breaking Change**: All references to \"sender\" in the
code have been renamed to \"correspondent\" to better reflect the
- Potentially **Breaking Change**: All references to "sender" in the
code have been renamed to "correspondent" to better reflect the
nature of the property (one could quite reasonably scan a document
before sending it to someone.)
- [\#67](https://github.com/the-paperless-project/paperless/issues/67):
@ -2360,7 +2344,7 @@ this big change.
contributing conversation that lead to this change.
- [\#20](https://github.com/the-paperless-project/paperless/issues/20):
Added _unpaper_ support to help in cleaning up the scanned image
before it\'s OCR\'d. Thanks to [Pit](https://github.com/pitkley) for
before it's OCR'd. Thanks to [Pit](https://github.com/pitkley) for
this one.
- [\#71](https://github.com/the-paperless-project/paperless/issues/71)
Added (encrypted) thumbnails in anticipation of a proper UI.

View File

@ -1,337 +0,0 @@
import sphinx_rtd_theme
__version__ = None
__full_version_str__ = None
__major_minor_version_str__ = None
exec(open("../src/paperless/version.py").read())
extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.intersphinx",
"sphinx.ext.todo",
"sphinx.ext.imgmath",
"sphinx.ext.viewcode",
"sphinx_rtd_theme",
"myst_parser",
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]
# The suffix of source filenames.
source_suffix = {
".rst": "restructuredtext",
".md": "markdown",
}
# The encoding of source files.
# source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = "index"
# General information about the project.
project = "Paperless-ngx"
copyright = "2015-2022, Daniel Quinn, Jonas Winkler, and the paperless-ngx team"
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
#
# If the build process ever explodes here, it's because you've set the version
# number in paperless.version to a tuple with 3 numbers in it.
#
# The short X.Y version.
version = __major_minor_version_str__
# The full version, including alpha/beta/rc tags.
release = __full_version_str__
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
# language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
# today = ''
# Else, today_fmt is used as the format for a strftime call.
# today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ["_build"]
# The reST default role (used for this markup: `text`) to use for all
# documents.
# default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
# add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
# add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = "sphinx"
# A list of ignored prefixes for module index sorting.
# modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
# keep_warnings = False
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = "sphinx_rtd_theme"
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
# html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
# html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
# html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
# html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
# html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ["_static"]
# These paths are either relative to html_static_path
# or fully qualified paths (eg. https://...)
html_css_files = [
"css/custom.css",
]
html_js_files = [
"js/darkmode.js",
]
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
# html_extra_path = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
# html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
# html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
# html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
# html_additional_pages = {}
# If false, no module index is generated.
# html_domain_indices = True
# If false, no index is generated.
# html_use_index = True
# If true, the index is split into individual pages for each letter.
# html_split_index = False
# If true, links to the reST sources are added to the pages.
# html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
# html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
# html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
# html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
# html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = "paperless"
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
("index", "paperless.tex", "Paperless Documentation", "Daniel Quinn", "manual"),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
# latex_use_parts = False
# If true, show page references after internal links.
# latex_show_pagerefs = False
# If true, show URL addresses after external links.
# latex_show_urls = False
# Documents to append as an appendix to all manuals.
# latex_appendices = []
# If false, no module index is generated.
# latex_domain_indices = True
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [("index", "paperless", "Paperless Documentation", ["Daniel Quinn"], 1)]
# If true, show URL addresses after external links.
# man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(
"index",
"Paperless",
"Paperless Documentation",
"Daniel Quinn",
"paperless",
"Scan, index, and archive all of your paper documents.",
"Miscellaneous",
),
]
# Documents to append as an appendix to all manuals.
# texinfo_appendices = []
# If false, no module index is generated.
# texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
# texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
# texinfo_no_detailmenu = False
# -- Options for Epub output ----------------------------------------------
# Bibliographic Dublin Core info.
epub_title = "Paperless"
epub_author = "Daniel Quinn"
epub_publisher = "Daniel Quinn"
epub_copyright = "2015, Daniel Quinn"
# The basename for the epub file. It defaults to the project name.
# epub_basename = u'Paperless'
# The HTML theme for the epub output. Since the default themes are not optimized
# for small screen space, using the same theme for HTML and epub output is
# usually not wise. This defaults to 'epub', a theme designed to save visual
# space.
# epub_theme = 'epub'
# The language of the text. It defaults to the language option
# or en if the language is not set.
# epub_language = ''
# The scheme of the identifier. Typical schemes are ISBN or URL.
# epub_scheme = ''
# The unique identifier of the text. This can be a ISBN number
# or the project homepage.
# epub_identifier = ''
# A unique identification for the text.
# epub_uid = ''
# A tuple containing the cover image and cover page html template filenames.
# epub_cover = ()
# A sequence of (type, uri, title) tuples for the guide element of content.opf.
# epub_guide = ()
# HTML files that should be inserted before the pages created by sphinx.
# The format is a list of tuples containing the path and title.
# epub_pre_files = []
# HTML files shat should be inserted after the pages created by sphinx.
# The format is a list of tuples containing the path and title.
# epub_post_files = []
# A list of files that should not be packed into the epub file.
epub_exclude_files = ["search.html"]
# The depth of the table of contents in toc.ncx.
# epub_tocdepth = 3
# Allow duplicate toc entries.
# epub_tocdup = True
# Choose between 'default' and 'includehidden'.
# epub_tocscope = 'default'
# Fix unsupported image types using the PIL.
# epub_fix_images = False
# Scale large images.
# epub_max_image_width = 0
# How to display URL addresses: 'footnote', 'no', or 'inline'.
# epub_show_urls = 'inline'
# If false, no index is generated.
# epub_use_index = True
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {"http://docs.python.org/": None}

1037
docs/configuration.md Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,931 +0,0 @@
.. _configuration:
*************
Configuration
*************
Paperless provides a wide range of customizations.
Depending on how you run paperless, these settings have to be defined in different
places.
* If you run paperless on docker, ``paperless.conf`` is not used. Rather, configure
paperless by copying necessary options to ``docker-compose.env``.
* If you are running paperless on anything else, paperless will search for the
configuration file in these locations and use the first one it finds:
.. code::
/path/to/paperless/paperless.conf
/etc/paperless.conf
/usr/local/etc/paperless.conf
Required services
#################
PAPERLESS_REDIS=<url>
This is required for processing scheduled tasks such as email fetching, index
optimization and for training the automatic document matcher.
* If your Redis server needs login credentials PAPERLESS_REDIS = ``redis://<username>:<password>@<host>:<port>``
* With the requirepass option PAPERLESS_REDIS = ``redis://:<password>@<host>:<port>``
`More information on securing your Redis Instance <https://redis.io/docs/getting-started/#securing-redis>`_.
Defaults to redis://localhost:6379.
PAPERLESS_DBENGINE=<engine_name>
Optional, gives the ability to choose Postgres or MariaDB for database engine.
Available options are `postgresql` and `mariadb`.
Default is `postgresql`.
.. warning::
Using MariaDB comes with some caveats. See :ref:`advanced-mysql-caveats` for details.
PAPERLESS_DBHOST=<hostname>
By default, sqlite is used as the database backend. This can be changed here.
Set PAPERLESS_DBHOST and another database will be used instead of sqlite.
PAPERLESS_DBPORT=<port>
Adjust port if necessary.
Default is 5432.
PAPERLESS_DBNAME=<name>
Database name in PostgreSQL or MariaDB.
Defaults to "paperless".
PAPERLESS_DBUSER=<name>
Database user in PostgreSQL or MariaDB.
Defaults to "paperless".
PAPERLESS_DBPASS=<password>
Database password for PostgreSQL or MariaDB.
Defaults to "paperless".
PAPERLESS_DBSSLMODE=<mode>
SSL mode to use when connecting to PostgreSQL.
See `the official documentation about sslmode <https://www.postgresql.org/docs/current/libpq-ssl.html>`_.
Default is ``prefer``.
PAPERLESS_DB_TIMEOUT=<float>
Amount of time for a database connection to wait for the database to unlock.
Mostly applicable for an sqlite based installation, consider changing to postgresql
if you need to increase this.
Defaults to unset, keeping the Django defaults.
Paths and folders
#################
PAPERLESS_CONSUMPTION_DIR=<path>
This where your documents should go to be consumed. Make sure that it exists
and that the user running the paperless service can read/write its contents
before you start Paperless.
Don't change this when using docker, as it only changes the path within the
container. Change the local consumption directory in the docker-compose.yml
file instead.
Defaults to "../consume/", relative to the "src" directory.
PAPERLESS_DATA_DIR=<path>
This is where paperless stores all its data (search index, SQLite database,
classification model, etc).
Defaults to "../data/", relative to the "src" directory.
PAPERLESS_TRASH_DIR=<path>
Instead of removing deleted documents, they are moved to this directory.
This must be writeable by the user running paperless. When running inside
docker, ensure that this path is within a permanent volume (such as
"../media/trash") so it won't get lost on upgrades.
Defaults to empty (i.e. really delete documents).
PAPERLESS_MEDIA_ROOT=<path>
This is where your documents and thumbnails are stored.
You can set this and PAPERLESS_DATA_DIR to the same folder to have paperless
store all its data within the same volume.
Defaults to "../media/", relative to the "src" directory.
PAPERLESS_STATICDIR=<path>
Override the default STATIC_ROOT here. This is where all static files
created using "collectstatic" manager command are stored.
Unless you're doing something fancy, there is no need to override this.
Defaults to "../static/", relative to the "src" directory.
PAPERLESS_FILENAME_FORMAT=<format>
Changes the filenames paperless uses to store documents in the media directory.
See :ref:`advanced-file_name_handling` for details.
Default is none, which disables this feature.
PAPERLESS_FILENAME_FORMAT_REMOVE_NONE=<bool>
Tells paperless to replace placeholders in `PAPERLESS_FILENAME_FORMAT` that would resolve
to 'none' to be omitted from the resulting filename. This also holds true for directory
names.
See :ref:`advanced-file_name_handling` for details.
Defaults to `false` which disables this feature.
PAPERLESS_LOGGING_DIR=<path>
This is where paperless will store log files.
Defaults to "``PAPERLESS_DATA_DIR``/log/".
Logging
#######
PAPERLESS_LOGROTATE_MAX_SIZE=<num>
Maximum file size for log files before they are rotated, in bytes.
Defaults to 1 MiB.
PAPERLESS_LOGROTATE_MAX_BACKUPS=<num>
Number of rotated log files to keep.
Defaults to 20.
.. _hosting-and-security:
Hosting & Security
##################
PAPERLESS_SECRET_KEY=<key>
Paperless uses this to make session tokens. If you expose paperless on the
internet, you need to change this, since the default secret is well known.
Use any sequence of characters. The more, the better. You don't need to
remember this. Just face-roll your keyboard.
Default is listed in the file ``src/paperless/settings.py``.
PAPERLESS_URL=<url>
This setting can be used to set the three options below (ALLOWED_HOSTS,
CORS_ALLOWED_HOSTS and CSRF_TRUSTED_ORIGINS). If the other options are
set the values will be combined with this one. Do not include a trailing
slash. E.g. https://paperless.domain.com
Defaults to empty string, leaving the other settings unaffected.
PAPERLESS_CSRF_TRUSTED_ORIGINS=<comma-separated-list>
A list of trusted origins for unsafe requests (e.g. POST). As of Django 4.0
this is required to access the Django admin via the web.
See https://docs.djangoproject.com/en/4.0/ref/settings/#csrf-trusted-origins
Can also be set using PAPERLESS_URL (see above).
Defaults to empty string, which does not add any origins to the trusted list.
PAPERLESS_ALLOWED_HOSTS=<comma-separated-list>
If you're planning on putting Paperless on the open internet, then you
really should set this value to the domain name you're using. Failing to do
so leaves you open to HTTP host header attacks:
https://docs.djangoproject.com/en/3.1/topics/security/#host-header-validation
Just remember that this is a comma-separated list, so "example.com" is fine,
as is "example.com,www.example.com", but NOT " example.com" or "example.com,"
Can also be set using PAPERLESS_URL (see above).
If manually set, please remember to include "localhost". Otherwise docker
healthcheck will fail.
Defaults to "*", which is all hosts.
PAPERLESS_CORS_ALLOWED_HOSTS=<comma-separated-list>
You need to add your servers to the list of allowed hosts that can do CORS
calls. Set this to your public domain name.
Can also be set using PAPERLESS_URL (see above).
Defaults to "http://localhost:8000".
PAPERLESS_FORCE_SCRIPT_NAME=<path>
To host paperless under a subpath url like example.com/paperless you set
this value to /paperless. No trailing slash!
Defaults to none, which hosts paperless at "/".
PAPERLESS_STATIC_URL=<path>
Override the STATIC_URL here. Unless you're hosting Paperless off a
subdomain like /paperless/, you probably don't need to change this.
If you do change it, be sure to include the trailing slash.
Defaults to "/static/".
.. note::
When hosting paperless behind a reverse proxy like Traefik or Nginx at a subpath e.g.
example.com/paperlessngx you will also need to set ``PAPERLESS_FORCE_SCRIPT_NAME``
(see above).
PAPERLESS_AUTO_LOGIN_USERNAME=<username>
Specify a username here so that paperless will automatically perform login
with the selected user.
.. danger::
Do not use this when exposing paperless on the internet. There are no
checks in place that would prevent you from doing this.
Defaults to none, which disables this feature.
PAPERLESS_ADMIN_USER=<username>
If this environment variable is specified, Paperless automatically creates
a superuser with the provided username at start. This is useful in cases
where you can not run the `createsuperuser` command separately, such as Kubernetes
or AWS ECS.
Requires `PAPERLESS_ADMIN_PASSWORD` to be set.
.. note::
This will not change an existing [super]user's password, nor will
it recreate a user that already exists. You can leave this throughout
the lifecycle of the containers.
PAPERLESS_ADMIN_MAIL=<email>
(Optional) Specify superuser email address. Only used when
`PAPERLESS_ADMIN_USER` is set.
Defaults to ``root@localhost``.
PAPERLESS_ADMIN_PASSWORD=<password>
Only used when `PAPERLESS_ADMIN_USER` is set.
This will be the password of the automatically created superuser.
PAPERLESS_COOKIE_PREFIX=<str>
Specify a prefix that is added to the cookies used by paperless to identify
the currently logged in user. This is useful for when you're running two
instances of paperless on the same host.
After changing this, you will have to login again.
Defaults to ``""``, which does not alter the cookie names.
PAPERLESS_ENABLE_HTTP_REMOTE_USER=<bool>
Allows authentication via HTTP_REMOTE_USER which is used by some SSO
applications.
.. warning::
This will allow authentication by simply adding a ``Remote-User: <username>`` header
to a request. Use with care! You especially *must* ensure that any such header is not
passed from your proxy server to paperless.
If you're exposing paperless to the internet directly, do not use this.
Also see the warning `in the official documentation <https://docs.djangoproject.com/en/3.1/howto/auth-remote-user/#configuration>`.
Defaults to `false` which disables this feature.
PAPERLESS_HTTP_REMOTE_USER_HEADER_NAME=<str>
If `PAPERLESS_ENABLE_HTTP_REMOTE_USER` is enabled, this property allows to
customize the name of the HTTP header from which the authenticated username
is extracted. Values are in terms of
[HttpRequest.META](https://docs.djangoproject.com/en/3.1/ref/request-response/#django.http.HttpRequest.META).
Thus, the configured value must start with `HTTP_` followed by the
normalized actual header name.
Defaults to `HTTP_REMOTE_USER`.
PAPERLESS_LOGOUT_REDIRECT_URL=<str>
URL to redirect the user to after a logout. This can be used together with
`PAPERLESS_ENABLE_HTTP_REMOTE_USER` to redirect the user back to the SSO
application's logout page.
Defaults to None, which disables this feature.
.. _configuration-ocr:
OCR settings
############
Paperless uses `OCRmyPDF <https://ocrmypdf.readthedocs.io/en/latest/>`_ for
performing OCR on documents and images. Paperless uses sensible defaults for
most settings, but all of them can be configured to your needs.
PAPERLESS_OCR_LANGUAGE=<lang>
Customize the language that paperless will attempt to use when
parsing documents.
It should be a 3-letter language code consistent with ISO
639: https://www.loc.gov/standards/iso639-2/php/code_list.php
Set this to the language most of your documents are written in.
This can be a combination of multiple languages such as ``deu+eng``,
in which case tesseract will use whatever language matches best.
Keep in mind that tesseract uses much more cpu time with multiple
languages enabled.
Defaults to "eng".
Note: If your language contains a '-' such as chi-sim, you must use chi_sim
PAPERLESS_OCR_MODE=<mode>
Tell paperless when and how to perform ocr on your documents. Four modes
are available:
* ``skip``: Paperless skips all pages and will perform ocr only on pages
where no text is present. This is the safest option.
* ``skip_noarchive``: In addition to skip, paperless won't create an
archived version of your documents when it finds any text in them.
This is useful if you don't want to have two almost-identical versions
of your digital documents in the media folder. This is the fastest option.
* ``redo``: Paperless will OCR all pages of your documents and attempt to
replace any existing text layers with new text. This will be useful for
documents from scanners that already performed OCR with insufficient
results. It will also perform OCR on purely digital documents.
This option may fail on some documents that have features that cannot
be removed, such as forms. In this case, the text from the document is
used instead.
* ``force``: Paperless rasterizes your documents, converting any text
into images and puts the OCRed text on top. This works for all documents,
however, the resulting document may be significantly larger and text
won't appear as sharp when zoomed in.
The default is ``skip``, which only performs OCR when necessary and always
creates archived documents.
Read more about this in the `OCRmyPDF documentation <https://ocrmypdf.readthedocs.io/en/latest/advanced.html#when-ocr-is-skipped>`_.
PAPERLESS_OCR_CLEAN=<mode>
Tells paperless to use ``unpaper`` to clean any input document before
sending it to tesseract. This uses more resources, but generally results
in better OCR results. The following modes are available:
* ``clean``: Apply unpaper.
* ``clean-final``: Apply unpaper, and use the cleaned images to build the
output file instead of the original images.
* ``none``: Do not apply unpaper.
Defaults to ``clean``.
.. note::
``clean-final`` is incompatible with ocr mode ``redo``. When both
``clean-final`` and the ocr mode ``redo`` is configured, ``clean``
is used instead.
PAPERLESS_OCR_DESKEW=<bool>
Tells paperless to correct skewing (slight rotation of input images mainly
due to improper scanning)
Defaults to ``true``, which enables this feature.
.. note::
Deskewing is incompatible with ocr mode ``redo``. Deskewing will get
disabled automatically if ``redo`` is used as the ocr mode.
PAPERLESS_OCR_ROTATE_PAGES=<bool>
Tells paperless to correct page rotation (90°, 180° and 270° rotation).
If you notice that paperless is not rotating incorrectly rotated
pages (or vice versa), try adjusting the threshold up or down (see below).
Defaults to ``true``, which enables this feature.
PAPERLESS_OCR_ROTATE_PAGES_THRESHOLD=<num>
Adjust the threshold for automatic page rotation by ``PAPERLESS_OCR_ROTATE_PAGES``.
This is an arbitrary value reported by tesseract. "15" is a very conservative value,
whereas "2" is a very aggressive option and will often result in correctly rotated pages
being rotated as well.
Defaults to "12".
PAPERLESS_OCR_OUTPUT_TYPE=<type>
Specify the the type of PDF documents that paperless should produce.
* ``pdf``: Modify the PDF document as little as possible.
* ``pdfa``: Convert PDF documents into PDF/A-2b documents, which is a
subset of the entire PDF specification and meant for storing
documents long term.
* ``pdfa-1``, ``pdfa-2``, ``pdfa-3`` to specify the exact version of
PDF/A you wish to use.
If not specified, ``pdfa`` is used. Remember that paperless also keeps
the original input file as well as the archived version.
PAPERLESS_OCR_PAGES=<num>
Tells paperless to use only the specified amount of pages for OCR. Documents
with less than the specified amount of pages get OCR'ed completely.
Specifying 1 here will only use the first page.
When combined with ``PAPERLESS_OCR_MODE=redo`` or ``PAPERLESS_OCR_MODE=force``,
paperless will not modify any text it finds on excluded pages and copy it
verbatim.
Defaults to 0, which disables this feature and always uses all pages.
PAPERLESS_OCR_IMAGE_DPI=<num>
Paperless will OCR any images you put into the system and convert them
into PDF documents. This is useful if your scanner produces images.
In order to do so, paperless needs to know the DPI of the image.
Most images from scanners will have this information embedded and
paperless will detect and use that information. In case this fails, it
uses this value as a fallback.
Set this to the DPI your scanner produces images at.
Default is none, which will automatically calculate image DPI so that
the produced PDF documents are A4 sized.
PAPERLESS_OCR_MAX_IMAGE_PIXELS=<num>
Paperless will raise a warning when OCRing images which are over this limit and
will not OCR images which are more than twice this limit. Note this does not
prevent the document from being consumed, but could result in missing text content.
If unset, will default to the value determined by
`Pillow <https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.MAX_IMAGE_PIXELS>`_.
.. note::
Increasing this limit could cause Paperless to consume additional resources
when consuming a file. Be sure you have sufficient system resources.
.. caution::
The limit is intended to prevent malicious files from consuming system resources
and causing crashes and other errors. Only increase this value if you are certain
your documents are not malicious and you need the text which was not OCRed
PAPERLESS_OCR_USER_ARGS=<json>
OCRmyPDF offers many more options. Use this parameter to specify any
additional arguments you wish to pass to OCRmyPDF. Since Paperless uses
the API of OCRmyPDF, you have to specify these in a format that can be
passed to the API. See `the API reference of OCRmyPDF <https://ocrmypdf.readthedocs.io/en/latest/api.html#reference>`_
for valid parameters. All command line options are supported, but they
use underscores instead of dashes.
.. caution::
Paperless has been tested to work with the OCR options provided
above. There are many options that are incompatible with each other,
so specifying invalid options may prevent paperless from consuming
any documents.
Specify arguments as a JSON dictionary. Keep note of lower case booleans
and double quoted parameter names and strings. Examples:
.. code:: json
{"deskew": true, "optimize": 3, "unpaper_args": "--pre-rotate 90"}
.. _configuration-tika:
Tika settings
#############
Paperless can make use of `Tika <https://tika.apache.org/>`_ and
`Gotenberg <https://gotenberg.dev/>`_ for parsing and
converting "Office" documents (such as ".doc", ".xlsx" and ".odt"). If you
wish to use this, you must provide a Tika server and a Gotenberg server,
configure their endpoints, and enable the feature.
PAPERLESS_TIKA_ENABLED=<bool>
Enable (or disable) the Tika parser.
Defaults to false.
PAPERLESS_TIKA_ENDPOINT=<url>
Set the endpoint URL were Paperless can reach your Tika server.
Defaults to "http://localhost:9998".
PAPERLESS_TIKA_GOTENBERG_ENDPOINT=<url>
Set the endpoint URL were Paperless can reach your Gotenberg server.
Defaults to "http://localhost:3000".
If you run paperless on docker, you can add those services to the docker-compose
file (see the provided ``docker-compose.sqlite-tika.yml`` file for reference). The changes
requires are as follows:
.. code:: yaml
services:
# ...
webserver:
# ...
environment:
# ...
PAPERLESS_TIKA_ENABLED: 1
PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000
PAPERLESS_TIKA_ENDPOINT: http://tika:9998
# ...
gotenberg:
image: gotenberg/gotenberg:7.6
restart: unless-stopped
command:
- "gotenberg"
- "--chromium-disable-routes=true"
tika:
image: ghcr.io/paperless-ngx/tika:latest
restart: unless-stopped
Add the configuration variables to the environment of the webserver (alternatively
put the configuration in the ``docker-compose.env`` file) and add the additional
services below the webserver service. Watch out for indentation.
Make sure to use the correct format `PAPERLESS_TIKA_ENABLED = 1` so python_dotenv can parse the statement correctly.
Software tweaks
###############
PAPERLESS_TASK_WORKERS=<num>
Paperless does multiple things in the background: Maintain the search index,
maintain the automatic matching algorithm, check emails, consume documents,
etc. This variable specifies how many things it will do in parallel.
Defaults to 1
PAPERLESS_THREADS_PER_WORKER=<num>
Furthermore, paperless uses multiple threads when consuming documents to
speed up OCR. This variable specifies how many pages paperless will process
in parallel on a single document.
.. caution::
Ensure that the product
PAPERLESS_TASK_WORKERS * PAPERLESS_THREADS_PER_WORKER
does not exceed your CPU core count or else paperless will be extremely slow.
If you want paperless to process many documents in parallel, choose a high
worker count. If you want paperless to process very large documents faster,
use a higher thread per worker count.
The default is a balance between the two, according to your CPU core count,
with a slight favor towards threads per worker:
+----------------+---------+---------+
| CPU core count | Workers | Threads |
+----------------+---------+---------+
| 1 | 1 | 1 |
+----------------+---------+---------+
| 2 | 2 | 1 |
+----------------+---------+---------+
| 4 | 2 | 2 |
+----------------+---------+---------+
| 6 | 2 | 3 |
+----------------+---------+---------+
| 8 | 2 | 4 |
+----------------+---------+---------+
| 12 | 3 | 4 |
+----------------+---------+---------+
| 16 | 4 | 4 |
+----------------+---------+---------+
If you only specify PAPERLESS_TASK_WORKERS, paperless will adjust
PAPERLESS_THREADS_PER_WORKER automatically.
PAPERLESS_WORKER_TIMEOUT=<num>
Machines with few cores or weak ones might not be able to finish OCR on
large documents within the default 1800 seconds. So extending this timeout
may prove to be useful on weak hardware setups.
PAPERLESS_WORKER_RETRY=<num>
If PAPERLESS_WORKER_TIMEOUT has been configured, the retry time for a task can
also be configured. By default, this value will be set to 10s more than the
worker timeout. This value should never be set less than the worker timeout.
PAPERLESS_TIME_ZONE=<timezone>
Set the time zone here.
See https://docs.djangoproject.com/en/3.1/ref/settings/#std:setting-TIME_ZONE
for details on how to set it.
Defaults to UTC.
.. _configuration-polling:
PAPERLESS_CONSUMER_POLLING=<num>
If paperless won't find documents added to your consume folder, it might
not be able to automatically detect filesystem changes. In that case,
specify a polling interval in seconds here, which will then cause paperless
to periodically check your consumption directory for changes. This will also
disable listening for file system changes with ``inotify``.
Defaults to 0, which disables polling and uses filesystem notifications.
PAPERLESS_CONSUMER_POLLING_RETRY_COUNT=<num>
If consumer polling is enabled, sets the number of times paperless will check for a
file to remain unmodified.
Defaults to 5.
PAPERLESS_CONSUMER_POLLING_DELAY=<num>
If consumer polling is enabled, sets the delay in seconds between each check (above) paperless
will do while waiting for a file to remain unmodified.
Defaults to 5.
.. _configuration-inotify:
PAPERLESS_CONSUMER_INOTIFY_DELAY=<num>
Sets the time in seconds the consumer will wait for additional events
from inotify before the consumer will consider a file ready and begin consumption.
Certain scanners or network setups may generate multiple events for a single file,
leading to multiple consumers working on the same file. Configure this to
prevent that.
Defaults to 0.5 seconds.
PAPERLESS_CONSUMER_DELETE_DUPLICATES=<bool>
When the consumer detects a duplicate document, it will not touch the
original document. This default behavior can be changed here.
Defaults to false.
PAPERLESS_CONSUMER_RECURSIVE=<bool>
Enable recursive watching of the consumption directory. Paperless will
then pickup files from files in subdirectories within your consumption
directory as well.
Defaults to false.
PAPERLESS_CONSUMER_SUBDIRS_AS_TAGS=<bool>
Set the names of subdirectories as tags for consumed files.
E.g. <CONSUMPTION_DIR>/foo/bar/file.pdf will add the tags "foo" and "bar" to
the consumed file. Paperless will create any tags that don't exist yet.
This is useful for sorting documents with certain tags such as ``car`` or
``todo`` prior to consumption. These folders won't be deleted.
PAPERLESS_CONSUMER_RECURSIVE must be enabled for this to work.
Defaults to false.
PAPERLESS_CONSUMER_ENABLE_BARCODES=<bool>
Enables the scanning and page separation based on detected barcodes.
This allows for scanning and adding multiple documents per uploaded
file, which are separated by one or multiple barcode pages.
For ease of use, it is suggested to use a standardized separation page,
e.g. `here <https://www.alliancegroup.co.uk/patch-codes.htm>`_.
If no barcodes are detected in the uploaded file, no page separation
will happen.
The original document will be removed and the separated pages will be
saved as pdf.
Defaults to false.
PAPERLESS_CONSUMER_BARCODE_TIFF_SUPPORT=<bool>
Whether TIFF image files should be scanned for barcodes.
This will automatically convert any TIFF image(s) to pdfs for later
processing.
This only has an effect, if PAPERLESS_CONSUMER_ENABLE_BARCODES has been
enabled.
Defaults to false.
PAPERLESS_CONSUMER_BARCODE_STRING=PATCHT
Defines the string to be detected as a separator barcode.
If paperless is used with the PATCH-T separator pages, users
shouldn't change this.
Defaults to "PATCHT"
PAPERLESS_CONVERT_MEMORY_LIMIT=<num>
On smaller systems, or even in the case of Very Large Documents, the consumer
may explode, complaining about how it's "unable to extend pixel cache". In
such cases, try setting this to a reasonably low value, like 32. The
default is to use whatever is necessary to do everything without writing to
disk, and units are in megabytes.
For more information on how to use this value, you should search
the web for "MAGICK_MEMORY_LIMIT".
Defaults to 0, which disables the limit.
PAPERLESS_CONVERT_TMPDIR=<path>
Similar to the memory limit, if you've got a small system and your OS mounts
/tmp as tmpfs, you should set this to a path that's on a physical disk, like
/home/your_user/tmp or something. ImageMagick will use this as scratch space
when crunching through very large documents.
For more information on how to use this value, you should search
the web for "MAGICK_TMPDIR".
Default is none, which disables the temporary directory.
PAPERLESS_POST_CONSUME_SCRIPT=<filename>
After a document is consumed, Paperless can trigger an arbitrary script if
you like. This script will be passed a number of arguments for you to work
with. For more information, take a look at :ref:`advanced-post_consume_script`.
The default is blank, which means nothing will be executed.
PAPERLESS_FILENAME_DATE_ORDER=<format>
Paperless will check the document text for document date information.
Use this setting to enable checking the document filename for date
information. The date order can be set to any option as specified in
https://dateparser.readthedocs.io/en/latest/settings.html#date-order.
The filename will be checked first, and if nothing is found, the document
text will be checked as normal.
A date in a filename must have some separators (`.`, `-`, `/`, etc)
for it to be parsed.
Defaults to none, which disables this feature.
PAPERLESS_NUMBER_OF_SUGGESTED_DATES=<num>
Paperless searches an entire document for dates. The first date found will
be used as the initial value for the created date. When this variable is
greater than 0 (or left to it's default value), paperless will also suggest
other dates found in the document, up to a maximum of this setting. Note that
duplicates will be removed, which can result in fewer dates displayed in the
frontend than this setting value.
The task to find all dates can be time-consuming and increases with a higher
(maximum) number of suggested dates and slower hardware.
Defaults to 3. Set to 0 to disable this feature.
PAPERLESS_THUMBNAIL_FONT_NAME=<filename>
Paperless creates thumbnails for plain text files by rendering the content
of the file on an image and uses a predefined font for that. This
font can be changed here.
Note that this won't have any effect on already generated thumbnails.
Defaults to ``/usr/share/fonts/liberation/LiberationSerif-Regular.ttf``.
PAPERLESS_IGNORE_DATES=<string>
Paperless parses a documents creation date from filename and file content.
You may specify a comma separated list of dates that should be ignored during
this process. This is useful for special dates (like date of birth) that appear
in documents regularly but are very unlikely to be the documents creation date.
The date is parsed using the order specified in PAPERLESS_DATE_ORDER
Defaults to an empty string to not ignore any dates.
PAPERLESS_DATE_ORDER=<format>
Paperless will try to determine the document creation date from its contents.
Specify the date format Paperless should expect to see within your documents.
This option defaults to DMY which translates to day first, month second, and year
last order. Characters D, M, or Y can be shuffled to meet the required order.
PAPERLESS_CONSUMER_IGNORE_PATTERNS=<json>
By default, paperless ignores certain files and folders in the consumption
directory, such as system files created by the Mac OS.
This can be adjusted by configuring a custom json array with patterns to exclude.
Defaults to ``[".DS_STORE/*", "._*", ".stfolder/*", ".stversions/*", ".localized/*", "desktop.ini"]``.
Binaries
########
There are a few external software packages that Paperless expects to find on
your system when it starts up. Unless you've done something creative with
their installation, you probably won't need to edit any of these. However,
if you've installed these programs somewhere where simply typing the name of
the program doesn't automatically execute it (ie. the program isn't in your
$PATH), then you'll need to specify the literal path for that program.
PAPERLESS_CONVERT_BINARY=<path>
Defaults to "convert".
PAPERLESS_GS_BINARY=<path>
Defaults to "gs".
.. _configuration-docker:
Docker-specific options
#######################
These options don't have any effect in ``paperless.conf``. These options adjust
the behavior of the docker container. Configure these in `docker-compose.env`.
PAPERLESS_WEBSERVER_WORKERS=<num>
The number of worker processes the webserver should spawn. More worker processes
usually result in the front end to load data much quicker. However, each worker process
also loads the entire application into memory separately, so increasing this value
will increase RAM usage.
Defaults to 1.
PAPERLESS_BIND_ADDR=<ip address>
The IP address the webserver will listen on inside the container. There are
special setups where you may need to configure this value to restrict the
Ip address or interface the webserver listens on.
Defaults to [::], meaning all interfaces, including IPv6.
PAPERLESS_PORT=<port>
The port number the webserver will listen on inside the container. There are
special setups where you may need this to avoid collisions with other
services (like using podman with multiple containers in one pod).
Don't change this when using Docker. To change the port the webserver is
reachable outside of the container, instead refer to the "ports" key in
``docker-compose.yml``.
Defaults to 8000.
USERMAP_UID=<uid>
The ID of the paperless user in the container. Set this to your actual user ID on the
host system, which you can get by executing
.. code:: shell-session
$ id -u
Paperless will change ownership on its folders to this user, so you need to get this right
in order to be able to write to the consumption directory.
Defaults to 1000.
USERMAP_GID=<gid>
The ID of the paperless Group in the container. Set this to your actual group ID on the
host system, which you can get by executing
.. code:: shell-session
$ id -g
Paperless will change ownership on its folders to this group, so you need to get this right
in order to be able to write to the consumption directory.
Defaults to 1000.
PAPERLESS_OCR_LANGUAGES=<list>
Additional OCR languages to install. By default, paperless comes with
English, German, Italian, Spanish and French. If your language is not in this list, install
additional languages with this configuration option:
.. code:: bash
PAPERLESS_OCR_LANGUAGES=tur ces
To actually use these languages, also set the default OCR language of paperless:
.. code:: bash
PAPERLESS_OCR_LANGUAGE=tur
Defaults to none, which does not install any additional languages.
PAPERLESS_ENABLE_FLOWER=<defined>
If this environment variable is defined, the Celery monitoring tool
`Flower <https://flower.readthedocs.io/en/latest/index.html>`_ will
be started by the container.
You can read more about this in the :ref:`advanced setup <advanced-celery-monitoring>`
documentation.
.. _configuration-update-checking:
Update Checking
###############
PAPERLESS_ENABLE_UPDATE_CHECK=<bool>
.. note::
This setting was deprecated in favor of a frontend setting after v1.9.2. A one-time
migration is performed for users who have this setting set. This setting is always
ignored if the corresponding frontend setting has been set.

469
docs/development.md Normal file
View File

@ -0,0 +1,469 @@
# Development
This section describes the steps you need to take to start development
on paperless-ngx.
Check out the source from github. The repository is organized in the
following way:
- `main` always represents the latest release and will only see
changes when a new release is made.
- `dev` contains the code that will be in the next release.
- `feature-X` contain bigger changes that will be in some release, but
not necessarily the next one.
When making functional changes to paperless, _always_ make your changes
on the `dev` branch.
Apart from that, the folder structure is as follows:
- `docs/` - Documentation.
- `src-ui/` - Code of the front end.
- `src/` - Code of the back end.
- `scripts/` - Various scripts that help with different parts of
development.
- `docker/` - Files required to build the docker image.
## Contributing to Paperless
Maybe you've been using Paperless for a while and want to add a feature
or two, or maybe you've come across a bug that you have some ideas how
to solve. The beauty of open source software is that you can see what's
wrong and help to get it fixed for everyone!
Before contributing please review our [code of
conduct](https://github.com/paperless-ngx/paperless-ngx/blob/main/CODE_OF_CONDUCT.md)
and other important information in the [contributing
guidelines](https://github.com/paperless-ngx/paperless-ngx/blob/main/CONTRIBUTING.md).
## Code formatting with pre-commit Hooks
To ensure a consistent style and formatting across the project source,
the project utilizes a Git [pre-commit]{.title-ref} hook to perform some
formatting and linting before a commit is allowed. That way, everyone
uses the same style and some common issues can be caught early on. See
below for installation instructions.
Once installed, hooks will run when you commit. If the formatting isn't
quite right or a linter catches something, the commit will be rejected.
You'll need to look at the output and fix the issue. Some hooks, such
as the Python formatting tool [black]{.title-ref}, will format failing
files, so all you need to do is [git add]{.title-ref} those files again
and retry your commit.
## Initial setup and first start
After you forked and cloned the code from github you need to perform a
first-time setup. To do the setup you need to perform the steps from the
following chapters in a certain order:
1. Install prerequisites + pipenv as mentioned in
`[Bare metal route](/setup#bare_metal)
2. Copy `paperless.conf.example` to `paperless.conf` and enable debug
mode.
3. Install the Angular CLI interface:
```shell-session
$ npm install -g @angular/cli
```
4. Install pre-commit
```shell-session
pre-commit install
```
5. Create `consume` and `media` folders in the cloned root folder.
```shell-session
mkdir -p consume media
```
6. You can now either \...
- install redis or
- use the included scripts/start-services.sh to use docker to fire
up a redis instance (and some other services such as tika,
gotenberg and a database server) or
- spin up a bare redis container
> ```shell-session
> docker run -d -p 6379:6379 --restart unless-stopped redis:latest
> ```
7. Install the python dependencies by performing in the src/ directory.
```shell-session
pipenv install --dev
```
> - Make sure you're using python 3.9.x or lower. Otherwise you might
> get issues with building dependencies. You can use
> [pyenv](https://github.com/pyenv/pyenv) to install a specific
> python version.
8. Generate the static UI so you can perform a login to get session
that is required for frontend development (this needs to be done one
time only). From src-ui directory:
```shell-session
npm install .
./node_modules/.bin/ng build --configuration production
```
9. Apply migrations and create a superuser for your dev instance:
```shell-session
python3 manage.py migrate
python3 manage.py createsuperuser
```
10. Now spin up the dev backend. Depending on which part of paperless
you're developing for, you need to have some or all of them
running.
> ```shell-session
> python3 manage.py runserver & python3 manage.py document_consumer & celery --app paperless worker
> ```
11. Login with the superuser credentials provided in step 8 at
`http://localhost:8000` to create a session that enables you to use
the backend.
Backend development environment is now ready, to start Frontend
development go to `/src-ui` and run `ng serve`. From there you can use
`http://localhost:4200` for a preview.
## Back end development
The backend is a django application. PyCharm works well for development,
but you can use whatever you want.
Configure the IDE to use the src/ folder as the base source folder.
Configure the following launch configurations in your IDE:
- python3 manage.py runserver
- celery \--app paperless worker
- python3 manage.py document_consumer
To start them all:
```shell-session
python3 manage.py runserver & python3 manage.py document_consumer & celery --app paperless worker
```
Testing and code style:
- Run `pytest` in the src/ directory to execute all tests. This also
generates a HTML coverage report. When runnings test, paperless.conf
is loaded as well. However: the tests rely on the default
configuration. This is not ideal. But for now, make sure no settings
except for DEBUG are overridden when testing.
- Coding style is enforced by the Git pre-commit hooks. These will
ensure your code is formatted and do some linting when you do a [git
commit]{.title-ref}.
- You can also run `black` manually to format your code
!!! note
The line length rule E501 is generally useful for getting multiple
source files next to each other on the screen. However, in some
cases, its just not possible to make some lines fit, especially
complicated IF cases. Append `# NOQA: E501` to disable this check
for certain lines.
## Front end development
The front end is built using Angular. In order to get started, you need
`npm`. Install the Angular CLI interface with
```shell-session
$ npm install -g @angular/cli
```
and make sure that it's on your path. Next, in the src-ui/ directory,
install the required dependencies of the project.
```shell-session
$ npm install
```
You can launch a development server by running
```shell-session
$ ng serve
```
This will automatically update whenever you save. However, in-place
compilation might fail on syntax errors, in which case you need to
restart it.
By default, the development server is available on
`http://localhost:4200/` and is configured to access the API at
`http://localhost:8000/api/`, which is the default of the backend. If
you enabled DEBUG on the back end, several security overrides for
allowed hosts, CORS and X-Frame-Options are in place so that the front
end behaves exactly as in production. This also relies on you being
logged into the back end. Without a valid session, The front end will
simply not work.
Testing and code style:
- The frontend code (.ts, .html, .scss) use `prettier` for code
formatting via the Git `pre-commit` hooks which run automatically on
commit. See
[above](#code-formatting-with-pre-commit-hooks) for installation. You can also run this via cli with a
command such as
```shell-session
$ git ls-files -- '*.ts' | xargs pre-commit run prettier --files
```
- Frontend testing uses jest and cypress. There is currently a need
for significantly more frontend tests. Unit tests and e2e tests,
respectively, can be run non-interactively with:
```shell-session
$ ng test
$ npm run e2e:ci
```
Cypress also includes a UI which can be run from within the `src-ui`
directory with
```shell-session
$ ./node_modules/.bin/cypress open
```
In order to build the front end and serve it as part of django, execute
```shell-session
$ ng build --prod
```
This will build the front end and put it in a location from which the
Django server will serve it as static content. This way, you can verify
that authentication is working.
## Localization
Paperless is available in many different languages. Since paperless
consists both of a django application and an Angular front end, both
these parts have to be translated separately.
### Front end localization
- The Angular front end does localization according to the [Angular
documentation](https://angular.io/guide/i18n).
- The source language of the project is "en_US".
- The source strings end up in the file "src-ui/messages.xlf".
- The translated strings need to be placed in the
"src-ui/src/locale/" folder.
- In order to extract added or changed strings from the source files,
call `ng xi18n --ivy`.
Adding new languages requires adding the translated files in the
"src-ui/src/locale/" folder and adjusting a couple files.
1. Adjust "src-ui/angular.json":
```json
"i18n": {
"sourceLocale": "en-US",
"locales": {
"de": "src/locale/messages.de.xlf",
"nl-NL": "src/locale/messages.nl_NL.xlf",
"fr": "src/locale/messages.fr.xlf",
"en-GB": "src/locale/messages.en_GB.xlf",
"pt-BR": "src/locale/messages.pt_BR.xlf",
"language-code": "language-file"
}
}
```
2. Add the language to the available options in
"src-ui/src/app/services/settings.service.ts":
```typescript
getLanguageOptions(): LanguageOption[] {
return [
{code: "en-us", name: $localize`English (US)`, englishName: "English (US)", dateInputFormat: "mm/dd/yyyy"},
{code: "en-gb", name: $localize`English (GB)`, englishName: "English (GB)", dateInputFormat: "dd/mm/yyyy"},
{code: "de", name: $localize`German`, englishName: "German", dateInputFormat: "dd.mm.yyyy"},
{code: "nl", name: $localize`Dutch`, englishName: "Dutch", dateInputFormat: "dd-mm-yyyy"},
{code: "fr", name: $localize`French`, englishName: "French", dateInputFormat: "dd/mm/yyyy"},
{code: "pt-br", name: $localize`Portuguese (Brazil)`, englishName: "Portuguese (Brazil)", dateInputFormat: "dd/mm/yyyy"}
// Add your new language here
]
}
```
`dateInputFormat` is a special string that defines the behavior of
the date input fields and absolutely needs to contain "dd", "mm"
and "yyyy".
3. Import and register the Angular data for this locale in
"src-ui/src/app/app.module.ts":
```typescript
import localeDe from '@angular/common/locales/de'
registerLocaleData(localeDe)
```
### Back end localization
A majority of the strings that appear in the back end appear only when
the admin is used. However, some of these are still shown on the front
end (such as error messages).
- The django application does localization according to the [django
documentation](https://docs.djangoproject.com/en/3.1/topics/i18n/translation/).
- The source language of the project is "en_US".
- Localization files end up in the folder "src/locale/".
- In order to extract strings from the application, call
`python3 manage.py makemessages -l en_US`. This is important after
making changes to translatable strings.
- The message files need to be compiled for them to show up in the
application. Call `python3 manage.py compilemessages` to do this.
The generated files don't get committed into git, since these are
derived artifacts. The build pipeline takes care of executing this
command.
Adding new languages requires adding the translated files in the
"src/locale/" folder and adjusting the file
"src/paperless/settings.py" to include the new language:
```python
LANGUAGES = [
("en-us", _("English (US)")),
("en-gb", _("English (GB)")),
("de", _("German")),
("nl-nl", _("Dutch")),
("fr", _("French")),
("pt-br", _("Portuguese (Brazil)")),
# Add language here.
]
```
## Building the documentation
The documentation is built using material-mkdocs, see their [documentation](https://squidfunk.github.io/mkdocs-material/reference/). If you want to build the documentation locally, this is how you do it:
1. Install python dependencies.
```shell-session
$ cd /path/to/paperless
$ pipenv install --dev
```
2. Build the documentation
```shell-session
$ cd /path/to/paperless
$ pipenv mkdocs build
```
## Building the Docker image
The docker image is primarily built by the GitHub actions workflow, but
it can be faster when developing to build and tag an image locally.
To provide the build arguments automatically, build the image using the
helper script `build-docker-image.sh`.
Building the docker image from source:
> ```shell-session
> ./build-docker-image.sh Dockerfile -t <your-tag>
> ```
## Extending Paperless
Paperless does not have any fancy plugin systems and will probably never
have. However, some parts of the application have been designed to allow
easy integration of additional features without any modification to the
base code.
### Making custom parsers
Paperless uses parsers to add documents to paperless. A parser is
responsible for:
- Retrieve the content from the original
- Create a thumbnail
- Optional: Retrieve a created date from the original
- Optional: Create an archived document from the original
Custom parsers can be added to paperless to support more file types. In
order to do that, you need to write the parser itself and announce its
existence to paperless.
The parser itself must extend `documents.parsers.DocumentParser` and
must implement the methods `parse` and `get_thumbnail`. You can provide
your own implementation to `get_date` if you don't want to rely on
paperless' default date guessing mechanisms.
```python
class MyCustomParser(DocumentParser):
def parse(self, document_path, mime_type):
# This method does not return anything. Rather, you should assign
# whatever you got from the document to the following fields:
# The content of the document.
self.text = "content"
# Optional: path to a PDF document that you created from the original.
self.archive_path = os.path.join(self.tempdir, "archived.pdf")
# Optional: "created" date of the document.
self.date = get_created_from_metadata(document_path)
def get_thumbnail(self, document_path, mime_type):
# This should return the path to a thumbnail you created for this
# document.
return os.path.join(self.tempdir, "thumb.png")
```
If you encounter any issues during parsing, raise a
`documents.parsers.ParseError`.
The `self.tempdir` directory is a temporary directory that is guaranteed
to be empty and removed after consumption finished. You can use that
directory to store any intermediate files and also use it to store the
thumbnail / archived document.
After that, you need to announce your parser to paperless. You need to
connect a handler to the `document_consumer_declaration` signal. Have a
look in the file `src/paperless_tesseract/apps.py` on how that's done.
The handler is a method that returns information about your parser:
```python
def myparser_consumer_declaration(sender, **kwargs):
return {
"parser": MyCustomParser,
"weight": 0,
"mime_types": {
"application/pdf": ".pdf",
"image/jpeg": ".jpg",
}
}
```
- `parser` is a reference to a class that extends `DocumentParser`.
- `weight` is used whenever two or more parsers are able to parse a
file: The parser with the higher weight wins. This can be used to
override the parsers provided by paperless.
- `mime_types` is a dictionary. The keys are the mime types your
parser supports and the value is the default file extension that
paperless should use when storing files and serving them for
download. We could guess that from the file extensions, but some
mime types have many extensions associated with them and the python
methods responsible for guessing the extension do not always return
the same value.

View File

@ -1,431 +0,0 @@
.. _extending:
Paperless-ngx Development
#########################
This section describes the steps you need to take to start development on paperless-ngx.
Check out the source from github. The repository is organized in the following way:
* ``main`` always represents the latest release and will only see changes
when a new release is made.
* ``dev`` contains the code that will be in the next release.
* ``feature-X`` contain bigger changes that will be in some release, but not
necessarily the next one.
When making functional changes to paperless, *always* make your changes on the ``dev`` branch.
Apart from that, the folder structure is as follows:
* ``docs/`` - Documentation.
* ``src-ui/`` - Code of the front end.
* ``src/`` - Code of the back end.
* ``scripts/`` - Various scripts that help with different parts of development.
* ``docker/`` - Files required to build the docker image.
Contributing to Paperless
=========================
Maybe you've been using Paperless for a while and want to add a feature or two,
or maybe you've come across a bug that you have some ideas how to solve. The
beauty of open source software is that you can see what's wrong and help to get
it fixed for everyone!
Before contributing please review our `code of conduct`_ and other important
information in the `contributing guidelines`_.
.. _code-formatting-with-pre-commit-hooks:
Code formatting with pre-commit Hooks
=====================================
To ensure a consistent style and formatting across the project source, the project
utilizes a Git `pre-commit` hook to perform some formatting and linting before a
commit is allowed. That way, everyone uses the same style and some common issues
can be caught early on. See below for installation instructions.
Once installed, hooks will run when you commit. If the formatting isn't quite right
or a linter catches something, the commit will be rejected. You'll need to look at the
output and fix the issue. Some hooks, such as the Python formatting tool `black`,
will format failing files, so all you need to do is `git add` those files again and
retry your commit.
Initial setup and first start
=============================
After you forked and cloned the code from github you need to perform a first-time setup.
To do the setup you need to perform the steps from the following chapters in a certain order:
1. Install prerequisites + pipenv as mentioned in :ref:`Bare metal route <setup-bare_metal>`
2. Copy ``paperless.conf.example`` to ``paperless.conf`` and enable debug mode.
3. Install the Angular CLI interface:
.. code:: shell-session
$ npm install -g @angular/cli
4. Install pre-commit
.. code:: shell-session
pre-commit install
5. Create ``consume`` and ``media`` folders in the cloned root folder.
.. code:: shell-session
mkdir -p consume media
6. You can now either ...
* install redis or
* use the included scripts/start-services.sh to use docker to fire up a redis instance (and some other services such as tika, gotenberg and a database server) or
* spin up a bare redis container
.. code:: shell-session
docker run -d -p 6379:6379 --restart unless-stopped redis:latest
7. Install the python dependencies by performing in the src/ directory.
.. code:: shell-session
pipenv install --dev
* Make sure you're using python 3.9.x or lower. Otherwise you might get issues with building dependencies. You can use `pyenv <https://github.com/pyenv/pyenv>`_ to install a specific python version.
8. Generate the static UI so you can perform a login to get session that is required for frontend development (this needs to be done one time only). From src-ui directory:
.. code:: shell-session
npm install .
./node_modules/.bin/ng build --configuration production
9. Apply migrations and create a superuser for your dev instance:
.. code:: shell-session
python3 manage.py migrate
python3 manage.py createsuperuser
10. Now spin up the dev backend. Depending on which part of paperless you're developing for, you need to have some or all of them running.
.. code:: shell-session
python3 manage.py runserver & python3 manage.py document_consumer & celery --app paperless worker
11. Login with the superuser credentials provided in step 8 at ``http://localhost:8000`` to create a session that enables you to use the backend.
Backend development environment is now ready, to start Frontend development go to ``/src-ui`` and run ``ng serve``. From there you can use ``http://localhost:4200`` for a preview.
Back end development
====================
The backend is a django application. PyCharm works well for development, but you can use whatever
you want.
Configure the IDE to use the src/ folder as the base source folder. Configure the following
launch configurations in your IDE:
* python3 manage.py runserver
* celery --app paperless worker
* python3 manage.py document_consumer
To start them all:
.. code:: shell-session
python3 manage.py runserver & python3 manage.py document_consumer & celery --app paperless worker
Testing and code style:
* Run ``pytest`` in the src/ directory to execute all tests. This also generates a HTML coverage
report. When runnings test, paperless.conf is loaded as well. However: the tests rely on the default
configuration. This is not ideal. But for now, make sure no settings except for DEBUG are overridden when testing.
* Coding style is enforced by the Git pre-commit hooks. These will ensure your code is formatted and do some
linting when you do a `git commit`.
* You can also run ``black`` manually to format your code
.. note::
The line length rule E501 is generally useful for getting multiple source files
next to each other on the screen. However, in some cases, its just not possible
to make some lines fit, especially complicated IF cases. Append ``# NOQA: E501``
to disable this check for certain lines.
Front end development
=====================
The front end is built using Angular. In order to get started, you need ``npm``.
Install the Angular CLI interface with
.. code:: shell-session
$ npm install -g @angular/cli
and make sure that it's on your path. Next, in the src-ui/ directory, install the
required dependencies of the project.
.. code:: shell-session
$ npm install
You can launch a development server by running
.. code:: shell-session
$ ng serve
This will automatically update whenever you save. However, in-place compilation might fail
on syntax errors, in which case you need to restart it.
By default, the development server is available on ``http://localhost:4200/`` and is configured
to access the API at ``http://localhost:8000/api/``, which is the default of the backend.
If you enabled DEBUG on the back end, several security overrides for allowed hosts, CORS and
X-Frame-Options are in place so that the front end behaves exactly as in production. This also
relies on you being logged into the back end. Without a valid session, The front end will simply
not work.
Testing and code style:
* The frontend code (.ts, .html, .scss) use ``prettier`` for code formatting via the Git
``pre-commit`` hooks which run automatically on commit. See
:ref:`above <code-formatting-with-pre-commit-hooks>` for installation. You can also run this
via cli with a command such as
.. code:: shell-session
$ git ls-files -- '*.ts' | xargs pre-commit run prettier --files
* Frontend testing uses jest and cypress. There is currently a need for significantly more
frontend tests. Unit tests and e2e tests, respectively, can be run non-interactively with:
.. code:: shell-session
$ ng test
$ npm run e2e:ci
Cypress also includes a UI which can be run from within the ``src-ui`` directory with
.. code:: shell-session
$ ./node_modules/.bin/cypress open
In order to build the front end and serve it as part of django, execute
.. code:: shell-session
$ ng build --prod
This will build the front end and put it in a location from which the Django server will serve
it as static content. This way, you can verify that authentication is working.
Localization
============
Paperless is available in many different languages. Since paperless consists both of a django
application and an Angular front end, both these parts have to be translated separately.
Front end localization
----------------------
* The Angular front end does localization according to the `Angular documentation <https://angular.io/guide/i18n>`_.
* The source language of the project is "en_US".
* The source strings end up in the file "src-ui/messages.xlf".
* The translated strings need to be placed in the "src-ui/src/locale/" folder.
* In order to extract added or changed strings from the source files, call ``ng xi18n --ivy``.
Adding new languages requires adding the translated files in the "src-ui/src/locale/" folder and adjusting a couple files.
1. Adjust "src-ui/angular.json":
.. code:: json
"i18n": {
"sourceLocale": "en-US",
"locales": {
"de": "src/locale/messages.de.xlf",
"nl-NL": "src/locale/messages.nl_NL.xlf",
"fr": "src/locale/messages.fr.xlf",
"en-GB": "src/locale/messages.en_GB.xlf",
"pt-BR": "src/locale/messages.pt_BR.xlf",
"language-code": "language-file"
}
}
2. Add the language to the available options in "src-ui/src/app/services/settings.service.ts":
.. code:: typescript
getLanguageOptions(): LanguageOption[] {
return [
{code: "en-us", name: $localize`English (US)`, englishName: "English (US)", dateInputFormat: "mm/dd/yyyy"},
{code: "en-gb", name: $localize`English (GB)`, englishName: "English (GB)", dateInputFormat: "dd/mm/yyyy"},
{code: "de", name: $localize`German`, englishName: "German", dateInputFormat: "dd.mm.yyyy"},
{code: "nl", name: $localize`Dutch`, englishName: "Dutch", dateInputFormat: "dd-mm-yyyy"},
{code: "fr", name: $localize`French`, englishName: "French", dateInputFormat: "dd/mm/yyyy"},
{code: "pt-br", name: $localize`Portuguese (Brazil)`, englishName: "Portuguese (Brazil)", dateInputFormat: "dd/mm/yyyy"}
// Add your new language here
]
}
``dateInputFormat`` is a special string that defines the behavior of the date input fields and absolutely needs to contain "dd", "mm" and "yyyy".
3. Import and register the Angular data for this locale in "src-ui/src/app/app.module.ts":
.. code:: typescript
import localeDe from '@angular/common/locales/de';
registerLocaleData(localeDe)
Back end localization
---------------------
A majority of the strings that appear in the back end appear only when the admin is used. However,
some of these are still shown on the front end (such as error messages).
* The django application does localization according to the `django documentation <https://docs.djangoproject.com/en/3.1/topics/i18n/translation/>`_.
* The source language of the project is "en_US".
* Localization files end up in the folder "src/locale/".
* In order to extract strings from the application, call ``python3 manage.py makemessages -l en_US``. This is important after making changes to translatable strings.
* The message files need to be compiled for them to show up in the application. Call ``python3 manage.py compilemessages`` to do this. The generated files don't get
committed into git, since these are derived artifacts. The build pipeline takes care of executing this command.
Adding new languages requires adding the translated files in the "src/locale/" folder and adjusting the file "src/paperless/settings.py" to include the new language:
.. code:: python
LANGUAGES = [
("en-us", _("English (US)")),
("en-gb", _("English (GB)")),
("de", _("German")),
("nl-nl", _("Dutch")),
("fr", _("French")),
("pt-br", _("Portuguese (Brazil)")),
# Add language here.
]
Building the documentation
==========================
The documentation is built using sphinx. I've configured ReadTheDocs to automatically build
the documentation when changes are pushed. If you want to build the documentation locally,
this is how you do it:
1. Install python dependencies.
.. code:: shell-session
$ cd /path/to/paperless
$ pipenv install --dev
2. Build the documentation
.. code:: shell-session
$ cd /path/to/paperless/docs
$ pipenv run make clean html
This will build the HTML documentation, and put the resulting files in the ``_build/html``
directory.
Building the Docker image
=========================
The docker image is primarily built by the GitHub actions workflow, but it can be
faster when developing to build and tag an image locally.
To provide the build arguments automatically, build the image using the helper
script ``build-docker-image.sh``.
Building the docker image from source:
.. code:: shell-session
./build-docker-image.sh Dockerfile -t <your-tag>
Extending Paperless
===================
Paperless does not have any fancy plugin systems and will probably never have. However,
some parts of the application have been designed to allow easy integration of additional
features without any modification to the base code.
Making custom parsers
---------------------
Paperless uses parsers to add documents to paperless. A parser is responsible for:
* Retrieve the content from the original
* Create a thumbnail
* Optional: Retrieve a created date from the original
* Optional: Create an archived document from the original
Custom parsers can be added to paperless to support more file types. In order to do that,
you need to write the parser itself and announce its existence to paperless.
The parser itself must extend ``documents.parsers.DocumentParser`` and must implement the
methods ``parse`` and ``get_thumbnail``. You can provide your own implementation to
``get_date`` if you don't want to rely on paperless' default date guessing mechanisms.
.. code:: python
class MyCustomParser(DocumentParser):
def parse(self, document_path, mime_type):
# This method does not return anything. Rather, you should assign
# whatever you got from the document to the following fields:
# The content of the document.
self.text = "content"
# Optional: path to a PDF document that you created from the original.
self.archive_path = os.path.join(self.tempdir, "archived.pdf")
# Optional: "created" date of the document.
self.date = get_created_from_metadata(document_path)
def get_thumbnail(self, document_path, mime_type):
# This should return the path to a thumbnail you created for this
# document.
return os.path.join(self.tempdir, "thumb.png")
If you encounter any issues during parsing, raise a ``documents.parsers.ParseError``.
The ``self.tempdir`` directory is a temporary directory that is guaranteed to be empty
and removed after consumption finished. You can use that directory to store any
intermediate files and also use it to store the thumbnail / archived document.
After that, you need to announce your parser to paperless. You need to connect a
handler to the ``document_consumer_declaration`` signal. Have a look in the file
``src/paperless_tesseract/apps.py`` on how that's done. The handler is a method
that returns information about your parser:
.. code:: python
def myparser_consumer_declaration(sender, **kwargs):
return {
"parser": MyCustomParser,
"weight": 0,
"mime_types": {
"application/pdf": ".pdf",
"image/jpeg": ".jpg",
}
}
* ``parser`` is a reference to a class that extends ``DocumentParser``.
* ``weight`` is used whenever two or more parsers are able to parse a file: The parser with
the higher weight wins. This can be used to override the parsers provided by
paperless.
* ``mime_types`` is a dictionary. The keys are the mime types your parser supports and the value
is the default file extension that paperless should use when storing files and serving them for
download. We could guess that from the file extensions, but some mime types have many extensions
associated with them and the python methods responsible for guessing the extension do not always
return the same value.
.. _code of conduct: https://github.com/paperless-ngx/paperless-ngx/blob/main/CODE_OF_CONDUCT.md
.. _contributing guidelines: https://github.com/paperless-ngx/paperless-ngx/blob/main/CONTRIBUTING.md

128
docs/faq.md Normal file
View File

@ -0,0 +1,128 @@
# Frequently Asked Questions
### _What's the general plan for Paperless-ngx?_
**A:** While Paperless-ngx is already considered largely
"feature-complete" it is a community-driven project and development
will be guided in this way. New features can be submitted via GitHub
discussions and "up-voted" by the community but this is not a
guarantee the feature will be implemented. This project will always be
open to collaboration in the form of PRs, ideas etc.
### _I'm using docker. Where are my documents?_
**A:** Your documents are stored inside the docker volume
`paperless_media`. Docker manages this volume automatically for you. It
is a persistent storage and will persist as long as you don't
explicitly delete it. The actual location depends on your host operating
system. On Linux, chances are high that this location is
```
/var/lib/docker/volumes/paperless_media/_data
```
!!! warning
Do not mess with this folder. Don't change permissions and don't move
files around manually. This folder is meant to be entirely managed by
docker and paperless.
### Let's say I want to switch tools in a year. Can I easily move
to other systems?\*
**A:** Your documents are stored as plain files inside the media folder.
You can always drag those files out of that folder to use them
elsewhere. Here are a couple notes about that.
- Paperless-ngx never modifies your original documents. It keeps
checksums of all documents and uses a scheduled sanity checker to
check that they remain the same.
- By default, paperless uses the internal ID of each document as its
filename. This might not be very convenient for export. However, you
can adjust the way files are stored in paperless by
`configuring the filename format <advanced-file_name_handling>`{.interpreted-text
role="ref"}.
- `The exporter <utilities-exporter>`{.interpreted-text role="ref"} is
another easy way to get your files out of paperless with reasonable
file names.
### _What file types does paperless-ngx support?_
**A:** Currently, the following files are supported:
- PDF documents, PNG images, JPEG images, TIFF images and GIF images
are processed with OCR and converted into PDF documents.
- Plain text documents are supported as well and are added verbatim to
paperless.
- With the optional Tika integration enabled (see
`Configuration <configuration-tika>`{.interpreted-text role="ref"}),
Paperless also supports various Office documents (.docx, .doc, odt,
.ppt, .pptx, .odp, .xls, .xlsx, .ods).
Paperless-ngx determines the type of a file by inspecting its content.
The file extensions do not matter.
### _Will paperless-ngx run on Raspberry Pi?_
**A:** The short answer is yes. I've tested it on a Raspberry Pi 3 B.
The long answer is that certain parts of Paperless will run very slow,
such as the OCR. On Raspberry Pi, try to OCR documents before feeding
them into paperless so that paperless can reuse the text. The web
interface is a lot snappier, since it runs in your browser and paperless
has to do much less work to serve the data.
!!! note
You can adjust some of the settings so that paperless uses less
processing power. See `setup-less_powerful_devices`{.interpreted-text
role="ref"} for details.
### _How do I install paperless-ngx on Raspberry Pi?_
**A:** Docker images are available for arm and arm64 hardware, so just
follow the docker-compose instructions. Apart from more required disk
space compared to a bare metal installation, docker comes with close to
zero overhead, even on Raspberry Pi.
If you decide to got with the bare metal route, be aware that some of
the python requirements do not have precompiled packages for ARM /
ARM64. Installation of these will require additional development
libraries and compilation will take a long time.
### _How do I run this on Unraid?_
**A:** Paperless-ngx is available as [community
app](https://unraid.net/community/apps?q=paperless-ngx) in Unraid. [Uli
Fahrer](https://github.com/Tooa) created a container template for that.
### _How do I run this on my toaster?_
**A:** I honestly don't know! As for all other devices that might be
able to run paperless, you're a bit on your own. If you can't run the
docker image, the documentation has instructions for bare metal
installs. I'm running paperless on an i3 processor from 2015 or so.
This is also what I use to test new releases with. Apart from that, I
also have a Raspberry Pi, which I occasionally build the image on and
see if it works.
### _How do I proxy this with NGINX?_
**A:** See `here <setup-nginx>`{.interpreted-text role="ref"}.
### _How do I get WebSocket support with Apache mod_wsgi_?
**A:** `mod_wsgi` by itself does not support ASGI. Paperless will
continue to work with WSGI, but certain features such as status
notifications about document consumption won't be available.
If you want to continue using `mod_wsgi`, you will have to run an
ASGI-enabled web server as well that processes WebSocket connections,
and configure Apache to redirect WebSocket connections to this server.
Multiple options for ASGI servers exist:
- `gunicorn` with `uvicorn` as the worker implementation (the default
of paperless)
- `daphne` as a standalone server, which is the reference
implementation for ASGI.
- `uvicorn` as a standalone server

View File

@ -1,117 +0,0 @@
**************************
Frequently asked questions
**************************
**Q:** *What's the general plan for Paperless-ngx?*
**A:** While Paperless-ngx is already considered largely "feature-complete" it is a community-driven
project and development will be guided in this way. New features can be submitted via
GitHub discussions and "up-voted" by the community but this is not a guarantee the feature
will be implemented. This project will always be open to collaboration in the form of PRs,
ideas etc.
**Q:** *I'm using docker. Where are my documents?*
**A:** Your documents are stored inside the docker volume ``paperless_media``.
Docker manages this volume automatically for you. It is a persistent storage
and will persist as long as you don't explicitly delete it. The actual location
depends on your host operating system. On Linux, chances are high that this location
is
.. code::
/var/lib/docker/volumes/paperless_media/_data
.. caution::
Do not mess with this folder. Don't change permissions and don't move
files around manually. This folder is meant to be entirely managed by docker
and paperless.
**Q:** *Let's say I want to switch tools in a year. Can I easily move to other systems?*
**A:** Your documents are stored as plain files inside the media folder. You can always drag those files
out of that folder to use them elsewhere. Here are a couple notes about that.
* Paperless-ngx never modifies your original documents. It keeps checksums of all documents and uses a
scheduled sanity checker to check that they remain the same.
* By default, paperless uses the internal ID of each document as its filename. This might not be very
convenient for export. However, you can adjust the way files are stored in paperless by
:ref:`configuring the filename format <advanced-file_name_handling>`.
* :ref:`The exporter <utilities-exporter>` is another easy way to get your files out of paperless with reasonable file names.
**Q:** *What file types does paperless-ngx support?*
**A:** Currently, the following files are supported:
* PDF documents, PNG images, JPEG images, TIFF images and GIF images are processed with OCR and converted into PDF documents.
* Plain text documents are supported as well and are added verbatim
to paperless.
* With the optional Tika integration enabled (see :ref:`Configuration <configuration-tika>`), Paperless also supports various
Office documents (.docx, .doc, odt, .ppt, .pptx, .odp, .xls, .xlsx, .ods).
Paperless-ngx determines the type of a file by inspecting its content. The
file extensions do not matter.
**Q:** *Will paperless-ngx run on Raspberry Pi?*
**A:** The short answer is yes. I've tested it on a Raspberry Pi 3 B.
The long answer is that certain parts of
Paperless will run very slow, such as the OCR. On Raspberry Pi,
try to OCR documents before feeding them into paperless so that paperless can
reuse the text. The web interface is a lot snappier, since it runs
in your browser and paperless has to do much less work to serve the data.
.. note::
You can adjust some of the settings so that paperless uses less processing
power. See :ref:`setup-less_powerful_devices` for details.
**Q:** *How do I install paperless-ngx on Raspberry Pi?*
**A:** Docker images are available for arm and arm64 hardware, so just follow
the docker-compose instructions. Apart from more required disk space compared to
a bare metal installation, docker comes with close to zero overhead, even on
Raspberry Pi.
If you decide to got with the bare metal route, be aware that some of the
python requirements do not have precompiled packages for ARM / ARM64. Installation
of these will require additional development libraries and compilation will take
a long time.
**Q:** *How do I run this on Unraid?*
**A:** Paperless-ngx is available as `community app <https://unraid.net/community/apps?q=paperless-ngx>`_
in Unraid. `Uli Fahrer <https://github.com/Tooa>`_ created a container template for that.
**Q:** *How do I run this on my toaster?*
**A:** I honestly don't know! As for all other devices that might be able
to run paperless, you're a bit on your own. If you can't run the docker image,
the documentation has instructions for bare metal installs. I'm running
paperless on an i3 processor from 2015 or so. This is also what I use to test
new releases with. Apart from that, I also have a Raspberry Pi, which I
occasionally build the image on and see if it works.
**Q:** *How do I proxy this with NGINX?*
**A:** See :ref:`here <setup-nginx>`.
.. _faq-mod_wsgi:
**Q:** *How do I get WebSocket support with Apache mod_wsgi*?
**A:** ``mod_wsgi`` by itself does not support ASGI. Paperless will continue
to work with WSGI, but certain features such as status notifications about
document consumption won't be available.
If you want to continue using ``mod_wsgi``, you will have to run an ASGI-enabled
web server as well that processes WebSocket connections, and configure Apache to
redirect WebSocket connections to this server. Multiple options for ASGI servers
exist:
* ``gunicorn`` with ``uvicorn`` as the worker implementation (the default of paperless)
* ``daphne`` as a standalone server, which is the reference implementation for ASGI.
* ``uvicorn`` as a standalone server

138
docs/index.md Normal file
View File

@ -0,0 +1,138 @@
<div class="grid-left" markdown>
![image](assets/logo_full_black.svg#only-light){.index-logo}
![image](assets/logo_full_white.svg#only-dark){.index-logo}
**Paperless-ngx** is a _community-supported_ open-source document management system that transforms your
physical documents into a searchable online archive so you can keep, well, _less paper_.
[Get started](/setup/){ .md-button .md-button--primary .index-callout }
[Demo](https://demo.paperless-ngx.com){ .md-button .md-button--secondary }
</div>
<div class="grid-right" markdown>
![image](assets/screenshots/documents-smallcards.png#only-light){.index-screenshot}
![image](assets/screenshots/documents-smallcards-dark.png#only-dark){.index-screenshot}
</div>
<div class="clear"></div>
## Why This Exists
Paper is a nightmare. Environmental issues aside, there's no excuse for
it in the 21st century. It takes up space, collects dust, doesn't
support any form of a search feature, indexing is tedious, it's heavy
and prone to damage & loss.
This software is designed to make "going paperless" easier. No more worrying
about finding stuff again, feed documents right from the post box into
the scanner and then shred them. Perhaps you might find it useful too.
## Paperless, a history
Paperless is a simple Django application running in two parts: a
_Consumer_ (the thing that does the indexing) and the _Web server_ (the
part that lets you search & download already-indexed documents). If you
want to learn more about its functions keep on reading after the
installation section.
Paperless-ngx is a document management system that transforms your
physical documents into a searchable online archive so you can keep,
well, _less paper_.
Paperless-ngx forked from paperless-ng to continue the great work and
distribute responsibility of supporting and advancing the project among
a team of people.
NG stands for both Angular (the framework used for the Frontend) and
next-gen. Publishing this project under a different name also avoids
confusion between paperless and paperless-ngx.
If you want to learn about what's different in paperless-ngx from
Paperless, check out these resources in the documentation:
- [Some screenshots](#screenshots) of the new UI are available.
- Read [this section](/advanced_usage/#advanced-automatic_matching) if you want to learn about how paperless automates all
tagging using machine learning.
- Paperless now comes with a `[proper email consumer](/usage/#usage-email) that's fully tested and production ready.
- Paperless creates searchable PDF/A documents from whatever you put into the consumption directory. This means
that you can select text in image-only documents coming from your scanner.
- See [this note](/administration/#utilities-encyption) about GnuPG encryption in paperless-ngx.
- Paperless is now integrated with a
[task processing queue](/setup#task_processor) that tells you at a glance when and why something is not working.
- The [changelog](/changelog) contains a detailed list of all changes in paperless-ngx.
## Screenshots
This is what Paperless-ngx looks like.
The dashboard shows customizable views on your document and allows
document uploads:
[![image](assets/screenshots/dashboard.png)](assets/screenshots/dashboard.png)
The document list provides three different styles to scroll through your
documents:
[![image](assets/screenshots/documents-table.png)](assets/screenshots/documents-table.png)
[![image](assets/screenshots/documents-smallcards.png)](assets/screenshots/documents-smallcards.png)
[![image](assets/screenshots/documents-largecards.png)](assets/screenshots/documents-largecards.png)
Paperless-ngx also supports dark mode:
[![image](assets/screenshots/documents-smallcards-dark.png)](assets/screenshots/documents-smallcards-dark.png)
Extensive filtering mechanisms:
[![image](assets/screenshots/documents-filter.png)](assets/screenshots/documents-filter.png)
Bulk editing of document tags, correspondents, etc.:
[![image](assets/screenshots/bulk-edit.png)](assets/screenshots/bulk-edit.png)
Side-by-side editing of documents:
[![image](assets/screenshots/editing.png)](assets/screenshots/editing.png)
Tag editing. This looks about the same for correspondents and document
types.
[![image](assets/screenshots/new-tag.png)](assets/screenshots/new-tag.png)
Searching provides auto complete and highlights the results.
[![image](assets/screenshots/search-preview.png)](assets/screenshots/search-preview.png)
[![image](assets/screenshots/search-results.png)](assets/screenshots/search-results.png)
Fancy mail filters!
[![image](assets/screenshots/mail-rules-edited.png)](assets/screenshots/mail-rules-edited.png)
Mobile devices are supported.
[![image](assets/screenshots/mobile.png)](assets/screenshots/mobile.png)
## Support
Community support is available via [GitHub Discussions](https://github.com/paperless-ngx/paperless-ngx/discussions/) and [the Matrix chat room](https://matrix.to/#/#paperless:matrix.org).
### Feature Requests
Feature requests can be submitted via [GitHub Discussions](https://github.com/paperless-ngx/paperless-ngx/discussions/categories/feature-requests) where you can search for existing ideas, add your own and vote for the ones you care about.
### Bugs
For bugs please [open an issue](https://github.com/paperless-ngx/paperless-ngx/issues) or [start a discussion](https://github.com/paperless-ngx/paperless-ngx/discussions/categories/support) if you have questions.
## Contributing
People interested in continuing the work on paperless-ngx are encouraged to reach out on [GitHub](https://github.com/paperless-ngx/paperless-ngx) or [the Matrix chat room](https://matrix.to/#/#paperless:matrix.org). If you would like to contribute to the project on an ongoing basis there are multiple teams (frontend, ci/cd, etc) that could use your help so please reach out!
### Translation
Paperless-ngx is available in many languages that are coordinated on [Crowdin](https://crwd.in/paperless-ngx). If you want to help out by translating paperless-ngx into your language, please head over to https://crwd.in/paperless-ngx, and thank you!
## Scanners & Software
Paperless-ngx is compatible with many different scanners and scanning tools. A user-maintained list of scanners and other software is available on [the wiki](https://github.com/paperless-ngx/paperless-ngx/wiki/Scanner-&-Software-Recommendations).

View File

@ -1,75 +0,0 @@
*********
Paperless
*********
Paperless is a simple Django application running in two parts:
a *Consumer* (the thing that does the indexing) and
the *Web server* (the part that lets you search &
download already-indexed documents). If you want to learn more about its
functions keep on reading after the installation section.
Why This Exists
===============
Paper is a nightmare. Environmental issues aside, there's no excuse for it in
the 21st century. It takes up space, collects dust, doesn't support any form
of a search feature, indexing is tedious, it's heavy and prone to damage &
loss.
I wrote this to make "going paperless" easier. I do not have to worry about
finding stuff again. I feed documents right from the post box into the scanner
and then shred them. Perhaps you might find it useful too.
Paperless-ngx
=============
Paperless-ngx is a document management system that transforms your physical
documents into a searchable online archive so you can keep, well, *less paper*.
Paperless-ngx forked from paperless-ng to continue the great work and
distribute responsibility of supporting and advancing the project among a team
of people.
NG stands for both Angular (the framework used for the
Frontend) and next-gen. Publishing this project under a different name also
avoids confusion between paperless and paperless-ngx.
If you want to learn about what's different in paperless-ngx from Paperless, check out these
resources in the documentation:
* :ref:`Some screenshots <screenshots>` of the new UI are available.
* Read :ref:`this section <advanced-automatic_matching>` if you want to
learn about how paperless automates all tagging using machine learning.
* Paperless now comes with a :ref:`proper email consumer <usage-email>`
that's fully tested and production ready.
* Paperless creates searchable PDF/A documents from whatever you put into
the consumption directory. This means that you can select text in
image-only documents coming from your scanner.
* See :ref:`this note <utilities-encyption>` about GnuPG encryption in
paperless-ngx.
* Paperless is now integrated with a
:ref:`task processing queue <setup-task_processor>` that tells you
at a glance when and why something is not working.
* The :doc:`changelog </changelog>` contains a detailed list of all changes
in paperless-ngx.
Contents
========
.. toctree::
:maxdepth: 1
setup
usage_overview
advanced_usage
administration
configuration
api
faq
troubleshooting
extending
scanners
screenshots
changelog

View File

@ -1 +0,0 @@
myst-parser==0.18.1

View File

@ -1,8 +0,0 @@
.. _scanners:
*******************
Scanners & Software
*******************
Paperless-ngx is compatible with many different scanners and scanning tools. A user-maintained list of scanners and other software is available on `the wiki <https://github.com/paperless-ngx/paperless-ngx/wiki/Scanner-&-Software-Recommendations>`_.

View File

@ -1,63 +0,0 @@
.. _screenshots:
***********
Screenshots
***********
This is what Paperless-ngx looks like.
The dashboard shows customizable views on your document and allows document uploads:
.. image:: _static/screenshots/dashboard.png
:target: _static/screenshots/dashboard.png
The document list provides three different styles to scroll through your documents:
.. image:: _static/screenshots/documents-table.png
:target: _static/screenshots/documents-table.png
.. image:: _static/screenshots/documents-smallcards.png
:target: _static/screenshots/documents-smallcards.png
.. image:: _static/screenshots/documents-largecards.png
:target: _static/screenshots/documents-largecards.png
Paperless-ngx also supports "dark mode":
.. image:: _static/screenshots/documents-smallcards-dark.png
:target: _static/screenshots/documents-smallcards-dark.png
Extensive filtering mechanisms:
.. image:: _static/screenshots/documents-filter.png
:target: _static/screenshots/documents-filter.png
Bulk editing of document tags, correspondents, etc.:
.. image:: _static/screenshots/bulk-edit.png
:target: _static/screenshots/bulk-edit.png
Side-by-side editing of documents:
.. image:: _static/screenshots/editing.png
:target: _static/screenshots/editing.png
Tag editing. This looks about the same for correspondents and document types.
.. image:: _static/screenshots/new-tag.png
:target: _static/screenshots/new-tag.png
Searching provides auto complete and highlights the results.
.. image:: _static/screenshots/search-preview.png
:target: _static/screenshots/search-preview.png
.. image:: _static/screenshots/search-results.png
:target: _static/screenshots/search-results.png
Fancy mail filters!
.. image:: _static/screenshots/mail-rules-edited.png
:target: _static/screenshots/mail-rules-edited.png
Mobile devices are supported.
.. image:: _static/screenshots/mobile.png
:target: _static/screenshots/mobile.png

852
docs/setup.md Normal file
View File

@ -0,0 +1,852 @@
## Installation
You can go multiple routes to setup and run Paperless:
- [Use the easy install docker script](/setup#docker_script)
- [Pull the image from Docker Hub](/setup#docker_hub)
- [Build the Docker image yourself](/setup#docker_build)
- [Install Paperless directly on your system manually (bare metal)](/setup#bare_metal)
The Docker routes are quick & easy. These are the recommended routes.
This configures all the stuff from the above automatically so that it
just works and uses sensible defaults for all configuration options.
Here you find a cheat-sheet for docker beginners: [CLI
Basics](https://www.sehn.tech/refs/devops-with-docker/)
The bare metal route is complicated to setup but makes it easier should
you want to contribute some code back. You need to configure and run the
above mentioned components yourself.
### Docker using the Installation Script {#docker_script}
Paperless provides an interactive installation script. This script will
ask you for a couple configuration options, download and create the
necessary configuration files, pull the docker image, start paperless
and create your user account. This script essentially performs all the
steps described in `setup-docker_hub`{.interpreted-text role="ref"}
automatically.
1. Make sure that docker and docker-compose are installed.
2. Download and run the installation script:
```shell-session
$ bash -c "$(curl -L https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/install-paperless-ngx.sh)"
```
### From GHCR / Docker Hub {#docker_hub}
1. Login with your user and create a folder in your home-directory
[mkdir -v \~/paperless-ngx]{.title-ref} to have a place for your
configuration files and consumption directory.
2. Go to the [/docker/compose directory on the project
page](https://github.com/paperless-ngx/paperless-ngx/tree/master/docker/compose)
and download one of the [docker-compose.\*.yml]{.title-ref} files,
depending on which database backend you want to use. Rename this
file to [docker-compose.yml]{.title-ref}. If you want to enable
optional support for Office documents, download a file with
[-tika]{.title-ref} in the file name. Download the
`docker-compose.env` file and the `.env` file as well and store them
in the same directory.
!!! tip
For new installations, it is recommended to use PostgreSQL as the
database backend.
3. Install [Docker](https://www.docker.com/) and
[docker-compose](https://docs.docker.com/compose/install/).
!!! warning
If you want to use the included `docker-compose.*.yml` file, you
need to have at least Docker version **17.09.0** and docker-compose
version **1.17.0**. To check do: [docker-compose -v]{.title-ref} or
[docker -v]{.title-ref}
See the [Docker installation guide]() on how to install the current
version of Docker for your operating system or Linux distribution of
choice. To get the latest version of docker-compose, follow the
[docker-compose installation guide]() if your package repository
doesn't include it.
4. Modify `docker-compose.yml` to your preferences. You may want to
change the path to the consumption directory. Find the line that
specifies where to mount the consumption directory:
```
- ./consume:/usr/src/paperless/consume
```
Replace the part BEFORE the colon with a local directory of your
choice:
```
- /home/jonaswinkler/paperless-inbox:/usr/src/paperless/consume
```
Don't change the part after the colon or paperless wont find your
documents.
You may also need to change the default port that the webserver will
use from the default (8000):
> ```
> ports:
> - 8000:8000
> ```
Replace the part BEFORE the colon with a port of your choice:
> ```
> ports:
> - 8010:8000
> ```
Don't change the part after the colon or edit other lines that
refer to port 8000. Modifying the part before the colon will map
requests on another port to the webserver running on the default
port.
**Rootless**
If you want to run Paperless as a rootless container, you will need
to do the following in your `docker-compose.yml`:
- set the `user` running the container to map to the `paperless`
user in the container. This value (`user_id` below), should be
the same id that `USERMAP_UID` and `USERMAP_GID` are set to in
the next step. See `USERMAP_UID` and `USERMAP_GID`
[here](/configuration#docker).
Your entry for Paperless should contain something like:
> ```
> webserver:
> image: ghcr.io/paperless-ngx/paperless-ngx:latest
> user: <user_id>
> ```
5. Modify `docker-compose.env`, following the comments in the file. The
most important change is to set `USERMAP_UID` and `USERMAP_GID` to
the uid and gid of your user on the host system. Use `id -u` and
`id -g` to get these.
This ensures that both the docker container and you on the host
machine have write access to the consumption directory. If your UID
and GID on the host system is 1000 (the default for the first normal
user on most systems), it will work out of the box without any
modifications. [id "username"]{.title-ref} to check.
!!! note
You can copy any setting from the file `paperless.conf.example` and
paste it here. Have a look at `configuration`{.interpreted-text
role="ref"} to see what's available.
!!! note
You can utilize Docker secrets for some configuration settings by
appending [\_FILE]{.title-ref} to some configuration values. This is
supported currently only by:
- PAPERLESS_DBUSER
- PAPERLESS_DBPASS
- PAPERLESS_SECRET_KEY
- PAPERLESS_AUTO_LOGIN_USERNAME
- PAPERLESS_ADMIN_USER
- PAPERLESS_ADMIN_MAIL
- PAPERLESS_ADMIN_PASSWORD
!!! warning
Some file systems such as NFS network shares don't support file
system notifications with `inotify`. When storing the consumption
directory on such a file system, paperless will not pick up new
files with the default configuration. You will need to use
`PAPERLESS_CONSUMER_POLLING`, which will disable inotify. See
[here](/configuration#polling).
6. Run `docker-compose pull`, followed by `docker-compose up -d`. This
will pull the image, create and start the necessary containers.
7. To be able to login, you will need a super user. To create it,
execute the following command:
```shell-session
$ docker-compose run --rm webserver createsuperuser
```
This will prompt you to set a username, an optional e-mail address
and finally a password (at least 8 characters).
8. The default `docker-compose.yml` exports the webserver on your local
port
8000\. If you did not change this, you should now be able to visit
your Paperless instance at `http://127.0.0.1:8000` or your servers
IP-Address:8000. Use the login credentials you have created with the
previous step.
### Build the Docker image yourself {#docker_build}
1. Clone the entire repository of paperless:
```shell-session
git clone https://github.com/paperless-ngx/paperless-ngx
```
The master branch always reflects the latest stable version.
2. Copy one of the `docker/compose/docker-compose.*.yml` to
`docker-compose.yml` in the root folder, depending on which database
backend you want to use. Copy `docker-compose.env` into the project
root as well.
3. In the `docker-compose.yml` file, find the line that instructs
docker-compose to pull the paperless image from Docker Hub:
```yaml
webserver:
image: ghcr.io/paperless-ngx/paperless-ngx:latest
```
and replace it with a line that instructs docker-compose to build
the image from the current working directory instead:
```yaml
webserver:
build:
context: .
args:
QPDF_VERSION: x.y.x
PIKEPDF_VERSION: x.y.z
PSYCOPG2_VERSION: x.y.z
JBIG2ENC_VERSION: 0.29
```
!!! note
You should match the build argument versions to the version for the
release you have checked out. These are pre-built images with
certain, more updated software. If you want to build these images
your self, that is possible, but beyond the scope of these steps.
4. Follow steps 3 to 8 of `setup-docker_hub`{.interpreted-text
role="ref"}. When asked to run `docker-compose pull` to pull the
image, do
```shell-session
$ docker-compose build
```
instead to build the image.
### Bare Metal Route {#bare_metal}
Paperless runs on linux only. The following procedure has been tested on
a minimal installation of Debian/Buster, which is the current stable
release at the time of writing. Windows is not and will never be
supported.
1. Install dependencies. Paperless requires the following packages.
- `python3` 3.8, 3.9
- `python3-pip`
- `python3-dev`
- `default-libmysqlclient-dev` for MariaDB
- `fonts-liberation` for generating thumbnails for plain text
files
- `imagemagick` >= 6 for PDF conversion
- `gnupg` for handling encrypted documents
- `libpq-dev` for PostgreSQL
- `libmagic-dev` for mime type detection
- `mariadb-client` for MariaDB compile time
- `mime-support` for mime type detection
- `libzbar0` for barcode detection
- `poppler-utils` for barcode detection
Use this list for your preferred package management:
```
python3 python3-pip python3-dev imagemagick fonts-liberation gnupg libpq-dev default-libmysqlclient-dev libmagic-dev mime-support libzbar0 poppler-utils
```
These dependencies are required for OCRmyPDF, which is used for text
recognition.
- `unpaper`
- `ghostscript`
- `icc-profiles-free`
- `qpdf`
- `liblept5`
- `libxml2`
- `pngquant` (suggested for certain PDF image optimizations)
- `zlib1g`
- `tesseract-ocr` >= 4.0.0 for OCR
- `tesseract-ocr` language packs (`tesseract-ocr-eng`,
`tesseract-ocr-deu`, etc)
Use this list for your preferred package management:
```
unpaper ghostscript icc-profiles-free qpdf liblept5 libxml2 pngquant zlib1g tesseract-ocr
```
On Raspberry Pi, these libraries are required as well:
- `libatlas-base-dev`
- `libxslt1-dev`
You will also need `build-essential`, `python3-setuptools` and
`python3-wheel` for installing some of the python dependencies.
2. Install `redis` >= 6.0 and configure it to start automatically.
3. Optional. Install `postgresql` and configure a database, user and
password for paperless. If you do not wish to use PostgreSQL,
MariaDB and SQLite are available as well.
!!! note
On bare-metal installations using SQLite, ensure the [JSON1
extension](https://code.djangoproject.com/wiki/JSON1Extension) is
enabled. This is usually the case, but not always.
4. Get the release archive from
<https://github.com/paperless-ngx/paperless-ngx/releases>. If you
clone the git repo as it is, you also have to compile the front end
by yourself. Extract the archive to a place from where you wish to
execute it, such as `/opt/paperless`.
5. Configure paperless. See `configuration`{.interpreted-text
role="ref"} for details. Edit the included `paperless.conf` and
adjust the settings to your needs. Required settings for getting
paperless running are:
- `PAPERLESS_REDIS` should point to your redis server, such as
<redis://localhost:6379>.
- `PAPERLESS_DBENGINE` optional, and should be one of [postgres,
mariadb, or sqlite]{.title-ref}
- `PAPERLESS_DBHOST` should be the hostname on which your
PostgreSQL server is running. Do not configure this to use
SQLite instead. Also configure port, database name, user and
password as necessary.
- `PAPERLESS_CONSUMPTION_DIR` should point to a folder which
paperless should watch for documents. You might want to have
this somewhere else. Likewise, `PAPERLESS_DATA_DIR` and
`PAPERLESS_MEDIA_ROOT` define where paperless stores its data.
If you like, you can point both to the same directory.
- `PAPERLESS_SECRET_KEY` should be a random sequence of
characters. It's used for authentication. Failure to do so
allows third parties to forge authentication credentials.
- `PAPERLESS_URL` if you are behind a reverse proxy. This should
point to your domain. Please see
`configuration`{.interpreted-text role="ref"} for more
information.
Many more adjustments can be made to paperless, especially the OCR
part. The following options are recommended for everyone:
- Set `PAPERLESS_OCR_LANGUAGE` to the language most of your
documents are written in.
- Set `PAPERLESS_TIME_ZONE` to your local time zone.
6. Create a system user under which you wish to run paperless.
```shell-session
adduser paperless --system --home /opt/paperless --group
```
7. Ensure that these directories exist and that the paperless user has
write permissions to the following directories:
- `/opt/paperless/media`
- `/opt/paperless/data`
- `/opt/paperless/consume`
Adjust as necessary if you configured different folders.
8. Install python requirements from the `requirements.txt` file. It is
up to you if you wish to use a virtual environment or not. First you
should update your pip, so it gets the actual packages.
```shell-session
sudo -Hu paperless pip3 install --upgrade pip
```
```shell-session
sudo -Hu paperless pip3 install -r requirements.txt
```
This will install all python dependencies in the home directory of
the new paperless user.
9. Go to `/opt/paperless/src`, and execute the following commands:
```bash
\# This creates the database schema.
sudo -Hu paperless python3 manage.py migrate
\# This creates your first paperless user
sudo -Hu paperless python3 manage.py createsuperuser
```
10. Optional: Test that paperless is working by executing
```bash
\# This collects static files from paperless and django.
sudo -Hu paperless python3 manage.py runserver
```
and pointing your browser to <http://localhost:8000/>.
!!! warning
This is a development server which should not be used in production.
It is not audited for security and performance is inferior to
production ready web servers.
!!! tip
This will not start the consumer. Paperless does this in a separate
process.
11. Setup systemd services to run paperless automatically. You may use
the service definition files included in the `scripts` folder as a
starting point.
Paperless needs the `webserver` script to run the webserver, the
`consumer` script to watch the input folder, `taskqueue` for the
background workers used to handle things like document consumption
and the `scheduler` script to run tasks such as email checking at
certain times .
!!! note
The `socket` script enables `gunicorn` to run on port 80 without
root privileges. For this you need to uncomment the
`Require=paperless-webserver.socket` in the `webserver` script
and configure `gunicorn` to listen on port 80 (see
`paperless/gunicorn.conf.py`).
You may need to adjust the path to the `gunicorn` executable. This
will be installed as part of the python dependencies, and is either
located in the `bin` folder of your virtual environment, or in
`~/.local/bin/` if no virtual environment is used.
These services rely on redis and optionally the database server, but
don't need to be started in any particular order. The example files
depend on redis being started. If you use a database server, you
should add additional dependencies.
!!! warning
The included scripts run a `gunicorn` standalone server, which is
fine for running paperless. It does support SSL, however, the
documentation of GUnicorn states that you should use a proxy server
in front of gunicorn instead.
For instructions on how to use nginx for that,
[see the instructions below](/setup#nginx).
12. Optional: Install a samba server and make the consumption folder
available as a network share.
13. Configure ImageMagick to allow processing of PDF documents. Most
distributions have this disabled by default, since PDF documents can
contain malware. If you don't do this, paperless will fall back to
ghostscript for certain steps such as thumbnail generation.
Edit `/etc/ImageMagick-6/policy.xml` and adjust
```
<policy domain="coder" rights="none" pattern="PDF" />
```
to
```
<policy domain="coder" rights="read|write" pattern="PDF" />
```
14. Optional: Install the
[jbig2enc](https://ocrmypdf.readthedocs.io/en/latest/jbig2.html)
encoder. This will reduce the size of generated PDF documents.
You'll most likely need to compile this by yourself, because this
software has been patented until around 2017 and binary packages are
not available for most distributions.
15. Optional: If using the NLTK machine learning processing (see
`PAPERLESS_ENABLE_NLTK` in `configuration`{.interpreted-text
role="ref"} for details), download the NLTK data for the Snowball
Stemmer, Stopwords and Punkt tokenizer to your
`PAPERLESS_DATA_DIR/nltk`. Refer to the [NLTK
instructions](https://www.nltk.org/data.html) for details on how to
download the data.
# Migrating to Paperless-ngx
Migration is possible both from Paperless-ng or directly from the
'original' Paperless.
## Migrating from Paperless-ng
Paperless-ngx is meant to be a drop-in replacement for Paperless-ng and
thus upgrading should be trivial for most users, especially when using
docker. However, as with any major change, it is recommended to take a
full backup first. Once you are ready, simply change the docker image to
point to the new source. E.g. if using Docker Compose, edit
`docker-compose.yml` and change:
```
image: jonaswinkler/paperless-ng:latest
```
to
```
image: ghcr.io/paperless-ngx/paperless-ngx:latest
```
and then run `docker-compose up -d` which will pull the new image
recreate the container. That's it!
Users who installed with the bare-metal route should also update their
Git clone to point to `https://github.com/paperless-ngx/paperless-ngx`,
e.g. using the command
`git remote set-url origin https://github.com/paperless-ngx/paperless-ngx`
and then pull the lastest version.
## Migrating from Paperless
At its core, paperless-ngx is still paperless and fully compatible.
However, some things have changed under the hood, so you need to adapt
your setup depending on how you installed paperless.
This setup describes how to update an existing paperless Docker
installation. The important things to keep in mind are as follows:
- Read the [changelog](/changelog) and
take note of breaking changes.
- You should decide if you want to stick with SQLite or want to
migrate your database to PostgreSQL. See
`setup-sqlite_to_psql`{.interpreted-text role="ref"} for details on
how to move your data from SQLite to PostgreSQL. Both work fine with
paperless. However, if you already have a database server running
for other services, you might as well use it for paperless as well.
- The task scheduler of paperless, which is used to execute periodic
tasks such as email checking and maintenance, requires a
[redis](https://redis.io/) message broker instance. The
docker-compose route takes care of that.
- The layout of the folder structure for your documents and data
remains the same, so you can just plug your old docker volumes into
paperless-ngx and expect it to find everything where it should be.
Migration to paperless-ngx is then performed in a few simple steps:
1. Stop paperless.
```bash
$ cd /path/to/current/paperless
$ docker-compose down
```
2. Do a backup for two purposes: If something goes wrong, you still
have your data. Second, if you don't like paperless-ngx, you can
switch back to paperless.
3. Download the latest release of paperless-ngx. You can either go with
the docker-compose files from
[here](https://github.com/paperless-ngx/paperless-ngx/tree/master/docker/compose)
or clone the repository to build the image yourself (see
[above](/setup#docker_build)). You can
either replace your current paperless folder or put paperless-ngx in
a different location.
!!! warning
Paperless-ngx includes a `.env` file. This will set the project name
for docker compose to `paperless`, which will also define the name
of the volumes by paperless-ngx. However, if you experience that
paperless-ngx is not using your old paperless volumes, verify the
names of your volumes with
``` shell-session
$ docker volume ls | grep _data
```
and adjust the project name in the `.env` file so that it matches
the name of the volumes before the `_data` part.
4. Download the `docker-compose.sqlite.yml` file to
`docker-compose.yml`. If you want to switch to PostgreSQL, do that
after you migrated your existing SQLite database.
5. Adjust `docker-compose.yml` and `docker-compose.env` to your needs.
See `setup-docker_hub`{.interpreted-text role="ref"} for details on
which edits are advised.
6. [Update paperless.](/administration#updating)
7. In order to find your existing documents with the new search
feature, you need to invoke a one-time operation that will create
the search index:
```shell-session
$ docker-compose run --rm webserver document_index reindex
```
This will migrate your database and create the search index. After
that, paperless will take care of maintaining the index by itself.
8. Start paperless-ngx.
```bash
$ docker-compose up -d
```
This will run paperless in the background and automatically start it
on system boot.
9. Paperless installed a permanent redirect to `admin/` in your
browser. This redirect is still in place and prevents access to the
new UI. Clear your browsing cache in order to fix this.
10. Optionally, follow the instructions below to migrate your existing
data to PostgreSQL.
## Migrating from LinuxServer.io Docker Image
As with any upgrades and large changes, it is highly recommended to
create a backup before starting. This assumes the image was running
using Docker Compose, but the instructions are translatable to Docker
commands as well.
1. Stop and remove the paperless container
2. If using an external database, stop the container
3. Update Redis configuration
a) If `REDIS_URL` is already set, change it to `PAPERLESS_REDIS`
and continue to step 4.
b) Otherwise, in the `docker-compose.yml` add a new service for
Redis, following [the example compose
files](https://github.com/paperless-ngx/paperless-ngx/tree/main/docker/compose)
c) Set the environment variable `PAPERLESS_REDIS` so it points to
the new Redis container
4. Update user mapping
a) If set, change the environment variable `PUID` to `USERMAP_UID`
b) If set, change the environment variable `PGID` to `USERMAP_GID`
5. Update configuration paths
a) Set the environment variable `PAPERLESS_DATA_DIR` to `/config`
6. Update media paths
a) Set the environment variable `PAPERLESS_MEDIA_ROOT` to
`/data/media`
7. Update timezone
a) Set the environment variable `PAPERLESS_TIME_ZONE` to the same
value as `TZ`
8. Modify the `image:` to point to
`ghcr.io/paperless-ngx/paperless-ngx:latest` or a specific version
if preferred.
9. Start the containers as before, using `docker-compose`.
## Moving data from SQLite to PostgreSQL or MySQL/MariaDB {#sqlite_to_psql}
Moving your data from SQLite to PostgreSQL or MySQL/MariaDB is done via
executing a series of django management commands as below. The commands
below use PostgreSQL, but are applicable to MySQL/MariaDB with the
!!! warning
Make sure that your SQLite database is migrated to the latest version.
Starting paperless will make sure that this is the case. If your try to
load data from an old database schema in SQLite into a newer database
schema in PostgreSQL, you will run into trouble.
!!! warning
On some database fields, PostgreSQL enforces predefined limits on
maximum length, whereas SQLite does not. The fields in question are the
title of documents (128 characters), names of document types, tags and
correspondents (128 characters), and filenames (1024 characters). If you
have data in these fields that surpasses these limits, migration to
PostgreSQL is not possible and will fail with an error.
!!! warning
MySQL is case insensitive by default, treating values like "Name" and
"NAME" as identical. See `advanced-mysql-caveats`{.interpreted-text
role="ref"} for details.
1. Stop paperless, if it is running.
2. Tell paperless to use PostgreSQL:
a) With docker, copy the provided `docker-compose.postgres.yml`
file to `docker-compose.yml`. Remember to adjust the consumption
directory, if necessary.
b) Without docker, configure the database in your `paperless.conf`
file. See `configuration`{.interpreted-text role="ref"} for
details.
3. Open a shell and initialize the database:
a) With docker, run the following command to open a shell within
the paperless container:
``` shell-session
$ cd /path/to/paperless
$ docker-compose run --rm webserver /bin/bash
```
This will launch the container and initialize the PostgreSQL
database.
b) Without docker, remember to activate any virtual environment,
switch to the `src` directory and create the database schema:
``` shell-session
$ cd /path/to/paperless/src
$ python3 manage.py migrate
```
This will not copy any data yet.
4. Dump your data from SQLite:
```shell-session
$ python3 manage.py dumpdata --database=sqlite --exclude=contenttypes --exclude=auth.Permission > data.json
```
5. Load your data into PostgreSQL:
```shell-session
$ python3 manage.py loaddata data.json
```
6. If operating inside Docker, you may exit the shell now.
```shell-session
$ exit
```
7. Start paperless.
## Moving back to Paperless
Lets say you migrated to Paperless-ngx and used it for a while, but
decided that you don't like it and want to move back (If you do, send
me a mail about what part you didn't like!), you can totally do that
with a few simple steps.
Paperless-ngx modified the database schema slightly, however, these
changes can be reverted while keeping your current data, so that your
current data will be compatible with original Paperless.
Execute this:
```shell-session
$ cd /path/to/paperless
$ docker-compose run --rm webserver migrate documents 0023
```
Or without docker:
```shell-session
$ cd /path/to/paperless/src
$ python3 manage.py migrate documents 0023
```
After that, you need to clear your cookies (Paperless-ngx comes with
updated dependencies that do cookie-processing differently) and probably
your cache as well.
# Considerations for less powerful devices {#less_powerful_devices}
Paperless runs on Raspberry Pi. However, some things are rather slow on
the Pi and configuring some options in paperless can help improve
performance immensely:
- Stick with SQLite to save some resources.
- Consider setting `PAPERLESS_OCR_PAGES` to 1, so that paperless will
only OCR the first page of your documents. In most cases, this page
contains enough information to be able to find it.
- `PAPERLESS_TASK_WORKERS` and `PAPERLESS_THREADS_PER_WORKER` are
configured to use all cores. The Raspberry Pi models 3 and up have 4
cores, meaning that paperless will use 2 workers and 2 threads per
worker. This may result in sluggish response times during
consumption, so you might want to lower these settings (example: 2
workers and 1 thread to always have some computing power left for
other tasks).
- Keep `PAPERLESS_OCR_MODE` at its default value `skip` and consider
OCR'ing your documents before feeding them into paperless. Some
scanners are able to do this! You might want to even specify
`skip_noarchive` to skip archive file generation for already ocr'ed
documents entirely.
- If you want to perform OCR on the device, consider using
`PAPERLESS_OCR_CLEAN=none`. This will speed up OCR times and use
less memory at the expense of slightly worse OCR results.
- If using docker, consider setting `PAPERLESS_WEBSERVER_WORKERS` to
1. This will save some memory.
- Consider setting `PAPERLESS_ENABLE_NLTK` to false, to disable the
more advanced language processing, which can take more memory and
processing time.
For details, refer to `configuration`{.interpreted-text role="ref"}.
!!! note
Updating the
[automatic matching algorithm](/advanced_usage#automatic_matching) takes quite a bit of time. However, the update mechanism
checks if your data has changed before doing the heavy lifting. If you
experience the algorithm taking too much cpu time, consider changing the
schedule in the admin interface to daily. You can also manually invoke
the task by changing the date and time of the next run to today/now.
The actual matching of the algorithm is fast and works on Raspberry Pi
as well as on any other device.
# Using nginx as a reverse proxy {#nginx}
If you want to expose paperless to the internet, you should hide it
behind a reverse proxy with SSL enabled.
In addition to the usual configuration for SSL, the following
configuration is required for paperless to operate:
```nginx
http {
# Adjust as required. This is the maximum size for file uploads.
# The default value 1M might be a little too small.
client_max_body_size 10M;
server {
location / {
# Adjust host and port as required.
proxy_pass http://localhost:8000/;
# These configuration options are required for WebSockets to work.
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
}
}
```
The `PAPERLESS_URL` configuration variable is also required when using a
reverse proxy. Please refer to the
`hosting-and-security`{.interpreted-text role="ref"} docs.
Also read
[this](https://channels.readthedocs.io/en/stable/deploying.html#nginx-supervisor-ubuntu),
towards the end of the section.

View File

@ -1,894 +0,0 @@
*****
Setup
*****
Overview of Paperless-ngx
#########################
Compared to paperless, paperless-ngx works a little different under the hood and has
more moving parts that work together. While this increases the complexity of
the system, it also brings many benefits.
Paperless consists of the following components:
* **The webserver:** This is pretty much the same as in paperless. It serves
the administration pages, the API, and the new frontend. This is the main
tool you'll be using to interact with paperless. You may start the webserver
with
.. code:: shell-session
$ cd /path/to/paperless/src/
$ gunicorn -c ../gunicorn.conf.py paperless.wsgi
or by any other means such as Apache ``mod_wsgi``.
* **The consumer:** This is what watches your consumption folder for documents.
However, the consumer itself does not really consume your documents.
Now it notifies a task processor that a new file is ready for consumption.
I suppose it should be named differently.
This was also used to check your emails, but that's now done elsewhere as well.
Start the consumer with the management command ``document_consumer``:
.. code:: shell-session
$ cd /path/to/paperless/src/
$ python3 manage.py document_consumer
.. _setup-task_processor:
* **The task processor:** Paperless relies on `Celery - Distributed Task Queue <https://docs.celeryq.dev/en/stable/index.html>`_
for doing most of the heavy lifting. This is a task queue that accepts tasks from
multiple sources and processes these in parallel. It also comes with a scheduler that executes
certain commands periodically.
This task processor is responsible for:
* Consuming documents. When the consumer finds new documents, it notifies the task processor to
start a consumption task.
* The task processor also performs the consumption of any documents you upload through
the web interface.
* Consuming emails. It periodically checks your configured accounts for new emails and
notifies the task processor to consume the attachment of an email.
* Maintaining the search index and the automatic matching algorithm. These are things that paperless
needs to do from time to time in order to operate properly.
This allows paperless to process multiple documents from your consumption folder in parallel! On
a modern multi core system, this makes the consumption process with full OCR blazingly fast.
The task processor comes with a built-in admin interface that you can use to check whenever any of the
tasks fail and inspect the errors (i.e., wrong email credentials, errors during consuming a specific
file, etc).
* A `redis <https://redis.io/>`_ message broker: This is a really lightweight service that is responsible
for getting the tasks from the webserver and the consumer to the task scheduler. These run in a different
process (maybe even on different machines!), and therefore, this is necessary.
* Optional: A database server. Paperless supports PostgreSQL, MariaDB and SQLite for storing its data.
Installation
############
You can go multiple routes to setup and run Paperless:
* :ref:`Use the easy install docker script <setup-docker_script>`
* :ref:`Pull the image from Docker Hub <setup-docker_hub>`
* :ref:`Build the Docker image yourself <setup-docker_build>`
* :ref:`Install Paperless directly on your system manually (bare metal) <setup-bare_metal>`
The Docker routes are quick & easy. These are the recommended routes. This configures all the stuff
from the above automatically so that it just works and uses sensible defaults for all configuration options.
Here you find a cheat-sheet for docker beginners: `CLI Basics <https://www.sehn.tech/refs/devops-with-docker/>`_
The bare metal route is complicated to setup but makes it easier
should you want to contribute some code back. You need to configure and
run the above mentioned components yourself.
.. _CLI Basics: https://www.sehn.tech/refs/devops-with-docker/
.. _setup-docker_script:
Install Paperless from Docker Hub using the installation script
===============================================================
Paperless provides an interactive installation script. This script will ask you
for a couple configuration options, download and create the necessary configuration files, pull the docker image, start paperless and create your user account. This script essentially
performs all the steps described in :ref:`setup-docker_hub` automatically.
1. Make sure that docker and docker-compose are installed.
2. Download and run the installation script:
.. code:: shell-session
$ bash -c "$(curl -L https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/install-paperless-ngx.sh)"
.. _setup-docker_hub:
Install Paperless from Docker Hub
=================================
1. Login with your user and create a folder in your home-directory `mkdir -v ~/paperless-ngx` to have a place for your configuration files and consumption directory.
2. Go to the `/docker/compose directory on the project page <https://github.com/paperless-ngx/paperless-ngx/tree/master/docker/compose>`_
and download one of the `docker-compose.*.yml` files, depending on which database backend you
want to use. Rename this file to `docker-compose.yml`.
If you want to enable optional support for Office documents, download a file with `-tika` in the file name.
Download the ``docker-compose.env`` file and the ``.env`` file as well and store them
in the same directory.
.. hint::
For new installations, it is recommended to use PostgreSQL as the database
backend.
3. Install `Docker`_ and `docker-compose`_.
.. caution::
If you want to use the included ``docker-compose.*.yml`` file, you
need to have at least Docker version **17.09.0** and docker-compose
version **1.17.0**.
To check do: `docker-compose -v` or `docker -v`
See the `Docker installation guide`_ on how to install the current
version of Docker for your operating system or Linux distribution of
choice. To get the latest version of docker-compose, follow the
`docker-compose installation guide`_ if your package repository doesn't
include it.
.. _Docker installation guide: https://docs.docker.com/engine/installation/
.. _docker-compose installation guide: https://docs.docker.com/compose/install/
4. Modify ``docker-compose.yml`` to your preferences. You may want to change the path
to the consumption directory. Find the line that specifies where
to mount the consumption directory:
.. code::
- ./consume:/usr/src/paperless/consume
Replace the part BEFORE the colon with a local directory of your choice:
.. code::
- /home/jonaswinkler/paperless-inbox:/usr/src/paperless/consume
Don't change the part after the colon or paperless wont find your documents.
You may also need to change the default port that the webserver will use
from the default (8000):
.. code::
ports:
- 8000:8000
Replace the part BEFORE the colon with a port of your choice:
.. code::
ports:
- 8010:8000
Don't change the part after the colon or edit other lines that refer to
port 8000. Modifying the part before the colon will map requests on another
port to the webserver running on the default port.
**Rootless**
If you want to run Paperless as a rootless container, you will need to do the
following in your ``docker-compose.yml``:
- set the ``user`` running the container to map to the ``paperless`` user in the
container.
This value (``user_id`` below), should be the same id that ``USERMAP_UID`` and
``USERMAP_GID`` are set to in the next step.
See ``USERMAP_UID`` and ``USERMAP_GID`` :ref:`here <configuration-docker>`.
Your entry for Paperless should contain something like:
.. code::
webserver:
image: ghcr.io/paperless-ngx/paperless-ngx:latest
user: <user_id>
5. Modify ``docker-compose.env``, following the comments in the file. The
most important change is to set ``USERMAP_UID`` and ``USERMAP_GID``
to the uid and gid of your user on the host system. Use ``id -u`` and
``id -g`` to get these.
This ensures that
both the docker container and you on the host machine have write access
to the consumption directory. If your UID and GID on the host system is
1000 (the default for the first normal user on most systems), it will
work out of the box without any modifications. `id "username"` to check.
.. note::
You can copy any setting from the file ``paperless.conf.example`` and paste it here.
Have a look at :ref:`configuration` to see what's available.
.. note::
You can utilize Docker secrets for some configuration settings by
appending `_FILE` to some configuration values. This is supported currently
only by:
* PAPERLESS_DBUSER
* PAPERLESS_DBPASS
* PAPERLESS_SECRET_KEY
* PAPERLESS_AUTO_LOGIN_USERNAME
* PAPERLESS_ADMIN_USER
* PAPERLESS_ADMIN_MAIL
* PAPERLESS_ADMIN_PASSWORD
.. caution::
Some file systems such as NFS network shares don't support file system
notifications with ``inotify``. When storing the consumption directory
on such a file system, paperless will not pick up new files
with the default configuration. You will need to use ``PAPERLESS_CONSUMER_POLLING``,
which will disable inotify. See :ref:`here <configuration-polling>`.
6. Run ``docker-compose pull``, followed by ``docker-compose up -d``.
This will pull the image, create and start the necessary containers.
7. To be able to login, you will need a super user. To create it, execute the
following command:
.. code-block:: shell-session
$ docker-compose run --rm webserver createsuperuser
This will prompt you to set a username, an optional e-mail address and
finally a password (at least 8 characters).
8. The default ``docker-compose.yml`` exports the webserver on your local port
8000. If you did not change this, you should now be able to visit your
Paperless instance at ``http://127.0.0.1:8000`` or your servers IP-Address:8000.
Use the login credentials you have created with the previous step.
.. _Docker: https://www.docker.com/
.. _docker-compose: https://docs.docker.com/compose/install/
.. _setup-docker_build:
Build the Docker image yourself
===============================
1. Clone the entire repository of paperless:
.. code:: shell-session
git clone https://github.com/paperless-ngx/paperless-ngx
The master branch always reflects the latest stable version.
2. Copy one of the ``docker/compose/docker-compose.*.yml`` to ``docker-compose.yml`` in the root folder,
depending on which database backend you want to use. Copy
``docker-compose.env`` into the project root as well.
3. In the ``docker-compose.yml`` file, find the line that instructs docker-compose to pull the paperless image from Docker Hub:
.. code:: yaml
webserver:
image: ghcr.io/paperless-ngx/paperless-ngx:latest
and replace it with a line that instructs docker-compose to build the image from the current working directory instead:
.. code:: yaml
webserver:
build:
context: .
args:
QPDF_VERSION: x.y.x
PIKEPDF_VERSION: x.y.z
PSYCOPG2_VERSION: x.y.z
JBIG2ENC_VERSION: 0.29
.. note::
You should match the build argument versions to the version for the release you have
checked out. These are pre-built images with certain, more updated software.
If you want to build these images your self, that is possible, but beyond
the scope of these steps.
4. Follow steps 3 to 8 of :ref:`setup-docker_hub`. When asked to run
``docker-compose pull`` to pull the image, do
.. code:: shell-session
$ docker-compose build
instead to build the image.
.. _setup-bare_metal:
Bare Metal Route
================
Paperless runs on linux only. The following procedure has been tested on a minimal
installation of Debian/Buster, which is the current stable release at the time of
writing. Windows is not and will never be supported.
1. Install dependencies. Paperless requires the following packages.
* ``python3`` 3.8, 3.9
* ``python3-pip``
* ``python3-dev``
* ``default-libmysqlclient-dev`` for MariaDB
* ``fonts-liberation`` for generating thumbnails for plain text files
* ``imagemagick`` >= 6 for PDF conversion
* ``gnupg`` for handling encrypted documents
* ``libpq-dev`` for PostgreSQL
* ``libmagic-dev`` for mime type detection
* ``mariadb-client`` for MariaDB compile time
* ``mime-support`` for mime type detection
* ``libzbar0`` for barcode detection
* ``poppler-utils`` for barcode detection
Use this list for your preferred package management:
.. code::
python3 python3-pip python3-dev imagemagick fonts-liberation gnupg libpq-dev default-libmysqlclient-dev libmagic-dev mime-support libzbar0 poppler-utils
These dependencies are required for OCRmyPDF, which is used for text recognition.
* ``unpaper``
* ``ghostscript``
* ``icc-profiles-free``
* ``qpdf``
* ``liblept5``
* ``libxml2``
* ``pngquant`` (suggested for certain PDF image optimizations)
* ``zlib1g``
* ``tesseract-ocr`` >= 4.0.0 for OCR
* ``tesseract-ocr`` language packs (``tesseract-ocr-eng``, ``tesseract-ocr-deu``, etc)
Use this list for your preferred package management:
.. code::
unpaper ghostscript icc-profiles-free qpdf liblept5 libxml2 pngquant zlib1g tesseract-ocr
On Raspberry Pi, these libraries are required as well:
* ``libatlas-base-dev``
* ``libxslt1-dev``
You will also need ``build-essential``, ``python3-setuptools`` and ``python3-wheel``
for installing some of the python dependencies.
2. Install ``redis`` >= 6.0 and configure it to start automatically.
3. Optional. Install ``postgresql`` and configure a database, user and password for paperless. If you do not wish
to use PostgreSQL, MariaDB and SQLite are available as well.
.. note::
On bare-metal installations using SQLite, ensure the
`JSON1 extension <https://code.djangoproject.com/wiki/JSON1Extension>`_ is enabled. This is
usually the case, but not always.
4. Get the release archive from `<https://github.com/paperless-ngx/paperless-ngx/releases>`_.
If you clone the git repo as it is, you also have to compile the front end by yourself.
Extract the archive to a place from where you wish to execute it, such as ``/opt/paperless``.
5. Configure paperless. See :ref:`configuration` for details. Edit the included ``paperless.conf`` and adjust the
settings to your needs. Required settings for getting paperless running are:
* ``PAPERLESS_REDIS`` should point to your redis server, such as redis://localhost:6379.
* ``PAPERLESS_DBENGINE`` optional, and should be one of `postgres, mariadb, or sqlite`
* ``PAPERLESS_DBHOST`` should be the hostname on which your PostgreSQL server is running. Do not configure this
to use SQLite instead. Also configure port, database name, user and password as necessary.
* ``PAPERLESS_CONSUMPTION_DIR`` should point to a folder which paperless should watch for documents. You might
want to have this somewhere else. Likewise, ``PAPERLESS_DATA_DIR`` and ``PAPERLESS_MEDIA_ROOT`` define where
paperless stores its data. If you like, you can point both to the same directory.
* ``PAPERLESS_SECRET_KEY`` should be a random sequence of characters. It's used for authentication. Failure
to do so allows third parties to forge authentication credentials.
* ``PAPERLESS_URL`` if you are behind a reverse proxy. This should point to your domain. Please see
:ref:`configuration` for more information.
Many more adjustments can be made to paperless, especially the OCR part. The following options are recommended
for everyone:
* Set ``PAPERLESS_OCR_LANGUAGE`` to the language most of your documents are written in.
* Set ``PAPERLESS_TIME_ZONE`` to your local time zone.
6. Create a system user under which you wish to run paperless.
.. code:: shell-session
adduser paperless --system --home /opt/paperless --group
7. Ensure that these directories exist
and that the paperless user has write permissions to the following directories:
* ``/opt/paperless/media``
* ``/opt/paperless/data``
* ``/opt/paperless/consume``
Adjust as necessary if you configured different folders.
8. Install python requirements from the ``requirements.txt`` file.
It is up to you if you wish to use a virtual environment or not. First you should update your pip, so it gets the actual packages.
.. code:: shell-session
sudo -Hu paperless pip3 install --upgrade pip
.. code:: shell-session
sudo -Hu paperless pip3 install -r requirements.txt
This will install all python dependencies in the home directory of
the new paperless user.
9. Go to ``/opt/paperless/src``, and execute the following commands:
.. code:: bash
# This creates the database schema.
sudo -Hu paperless python3 manage.py migrate
# This creates your first paperless user
sudo -Hu paperless python3 manage.py createsuperuser
10. Optional: Test that paperless is working by executing
.. code:: bash
# This collects static files from paperless and django.
sudo -Hu paperless python3 manage.py runserver
and pointing your browser to http://localhost:8000/.
.. warning::
This is a development server which should not be used in
production. It is not audited for security and performance
is inferior to production ready web servers.
.. hint::
This will not start the consumer. Paperless does this in a
separate process.
11. Setup systemd services to run paperless automatically. You may
use the service definition files included in the ``scripts`` folder
as a starting point.
Paperless needs the ``webserver`` script to run the webserver, the
``consumer`` script to watch the input folder, ``taskqueue`` for the background workers
used to handle things like document consumption and the ``scheduler`` script to run tasks such as
email checking at certain times .
The ``socket`` script enables ``gunicorn`` to run on port 80 without
root privileges. For this you need to uncomment the ``Require=paperless-webserver.socket``
in the ``webserver`` script and configure ``gunicorn`` to listen on port 80 (see ``paperless/gunicorn.conf.py``).
You may need to adjust the path to the ``gunicorn`` executable. This
will be installed as part of the python dependencies, and is either located
in the ``bin`` folder of your virtual environment, or in ``~/.local/bin/`` if
no virtual environment is used.
These services rely on redis and optionally the database server, but
don't need to be started in any particular order. The example files
depend on redis being started. If you use a database server, you should
add additional dependencies.
.. caution::
The included scripts run a ``gunicorn`` standalone server,
which is fine for running paperless. It does support SSL,
however, the documentation of GUnicorn states that you should
use a proxy server in front of gunicorn instead.
For instructions on how to use nginx for that,
:ref:`see the instructions below <setup-nginx>`.
12. Optional: Install a samba server and make the consumption folder
available as a network share.
13. Configure ImageMagick to allow processing of PDF documents. Most distributions have
this disabled by default, since PDF documents can contain malware. If
you don't do this, paperless will fall back to ghostscript for certain steps
such as thumbnail generation.
Edit ``/etc/ImageMagick-6/policy.xml`` and adjust
.. code::
<policy domain="coder" rights="none" pattern="PDF" />
to
.. code::
<policy domain="coder" rights="read|write" pattern="PDF" />
14. Optional: Install the `jbig2enc <https://ocrmypdf.readthedocs.io/en/latest/jbig2.html>`_
encoder. This will reduce the size of generated PDF documents. You'll most likely need
to compile this by yourself, because this software has been patented until around 2017 and
binary packages are not available for most distributions.
15. Optional: If using the NLTK machine learning processing (see ``PAPERLESS_ENABLE_NLTK`` in
:ref:`configuration` for details), download the NLTK data for the Snowball Stemmer, Stopwords
and Punkt tokenizer to your ``PAPERLESS_DATA_DIR/nltk``. Refer to
the `NLTK instructions <https://www.nltk.org/data.html>`_ for details on how to
download the data.
Migrating to Paperless-ngx
##########################
Migration is possible both from Paperless-ng or directly from the 'original' Paperless.
Migrating from Paperless-ng
===========================
Paperless-ngx is meant to be a drop-in replacement for Paperless-ng and thus upgrading should be
trivial for most users, especially when using docker. However, as with any major change, it is
recommended to take a full backup first. Once you are ready, simply change the docker image to
point to the new source. E.g. if using Docker Compose, edit ``docker-compose.yml`` and change:
.. code::
image: jonaswinkler/paperless-ng:latest
to
.. code::
image: ghcr.io/paperless-ngx/paperless-ngx:latest
and then run ``docker-compose up -d`` which will pull the new image recreate the container.
That's it!
Users who installed with the bare-metal route should also update their Git clone to point to
``https://github.com/paperless-ngx/paperless-ngx``, e.g. using the command
``git remote set-url origin https://github.com/paperless-ngx/paperless-ngx`` and then pull the
lastest version.
Migrating from Paperless
========================
At its core, paperless-ngx is still paperless and fully compatible. However, some
things have changed under the hood, so you need to adapt your setup depending on
how you installed paperless.
This setup describes how to update an existing paperless Docker installation.
The important things to keep in mind are as follows:
* Read the :doc:`changelog </changelog>` and take note of breaking changes.
* You should decide if you want to stick with SQLite or want to migrate your database
to PostgreSQL. See :ref:`setup-sqlite_to_psql` for details on how to move your data from
SQLite to PostgreSQL. Both work fine with paperless. However, if you already have a
database server running for other services, you might as well use it for paperless as well.
* The task scheduler of paperless, which is used to execute periodic tasks
such as email checking and maintenance, requires a `redis`_ message broker
instance. The docker-compose route takes care of that.
* The layout of the folder structure for your documents and data remains the
same, so you can just plug your old docker volumes into paperless-ngx and
expect it to find everything where it should be.
Migration to paperless-ngx is then performed in a few simple steps:
1. Stop paperless.
.. code:: bash
$ cd /path/to/current/paperless
$ docker-compose down
2. Do a backup for two purposes: If something goes wrong, you still have your
data. Second, if you don't like paperless-ngx, you can switch back to
paperless.
3. Download the latest release of paperless-ngx. You can either go with the
docker-compose files from `here <https://github.com/paperless-ngx/paperless-ngx/tree/master/docker/compose>`__
or clone the repository to build the image yourself (see :ref:`above <setup-docker_build>`).
You can either replace your current paperless folder or put paperless-ngx
in a different location.
.. caution::
Paperless-ngx includes a ``.env`` file. This will set the
project name for docker compose to ``paperless``, which will also define the name
of the volumes by paperless-ngx. However, if you experience that paperless-ngx
is not using your old paperless volumes, verify the names of your volumes with
.. code:: shell-session
$ docker volume ls | grep _data
and adjust the project name in the ``.env`` file so that it matches the name
of the volumes before the ``_data`` part.
4. Download the ``docker-compose.sqlite.yml`` file to ``docker-compose.yml``.
If you want to switch to PostgreSQL, do that after you migrated your existing
SQLite database.
5. Adjust ``docker-compose.yml`` and ``docker-compose.env`` to your needs.
See :ref:`setup-docker_hub` for details on which edits are advised.
6. :ref:`Update paperless. <administration-updating>`
7. In order to find your existing documents with the new search feature, you need
to invoke a one-time operation that will create the search index:
.. code:: shell-session
$ docker-compose run --rm webserver document_index reindex
This will migrate your database and create the search index. After that,
paperless will take care of maintaining the index by itself.
8. Start paperless-ngx.
.. code:: bash
$ docker-compose up -d
This will run paperless in the background and automatically start it on system boot.
9. Paperless installed a permanent redirect to ``admin/`` in your browser. This
redirect is still in place and prevents access to the new UI. Clear your
browsing cache in order to fix this.
10. Optionally, follow the instructions below to migrate your existing data to PostgreSQL.
Migrating from LinuxServer.io Docker Image
==========================================
As with any upgrades and large changes, it is highly recommended to create a backup before
starting. This assumes the image was running using Docker Compose, but the instructions
are translatable to Docker commands as well.
1. Stop and remove the paperless container
2. If using an external database, stop the container
3. Update Redis configuration
a) If ``REDIS_URL`` is already set, change it to ``PAPERLESS_REDIS`` and continue
to step 4.
b) Otherwise, in the ``docker-compose.yml`` add a new service for Redis,
following `the example compose files <https://github.com/paperless-ngx/paperless-ngx/tree/main/docker/compose>`_
c) Set the environment variable ``PAPERLESS_REDIS`` so it points to the new Redis container
4. Update user mapping
a) If set, change the environment variable ``PUID`` to ``USERMAP_UID``
b) If set, change the environment variable ``PGID`` to ``USERMAP_GID``
5. Update configuration paths
a) Set the environment variable ``PAPERLESS_DATA_DIR``
to ``/config``
6. Update media paths
a) Set the environment variable ``PAPERLESS_MEDIA_ROOT``
to ``/data/media``
7. Update timezone
a) Set the environment variable ``PAPERLESS_TIME_ZONE``
to the same value as ``TZ``
8. Modify the ``image:`` to point to ``ghcr.io/paperless-ngx/paperless-ngx:latest`` or
a specific version if preferred.
9. Start the containers as before, using ``docker-compose``.
.. _setup-sqlite_to_psql:
Moving data from SQLite to PostgreSQL or MySQL/MariaDB
======================================================
Moving your data from SQLite to PostgreSQL or MySQL/MariaDB is done via executing a series of django
management commands as below. The commands below use PostgreSQL, but are applicable to MySQL/MariaDB
with the
.. caution::
Make sure that your SQLite database is migrated to the latest version.
Starting paperless will make sure that this is the case. If your try to
load data from an old database schema in SQLite into a newer database
schema in PostgreSQL, you will run into trouble.
.. warning::
On some database fields, PostgreSQL enforces predefined limits on maximum
length, whereas SQLite does not. The fields in question are the title of documents
(128 characters), names of document types, tags and correspondents (128 characters),
and filenames (1024 characters). If you have data in these fields that surpasses these
limits, migration to PostgreSQL is not possible and will fail with an error.
.. warning::
MySQL is case insensitive by default, treating values like "Name" and "NAME" as identical.
See :ref:`advanced-mysql-caveats` for details.
1. Stop paperless, if it is running.
2. Tell paperless to use PostgreSQL:
a) With docker, copy the provided ``docker-compose.postgres.yml`` file to
``docker-compose.yml``. Remember to adjust the consumption directory,
if necessary.
b) Without docker, configure the database in your ``paperless.conf`` file.
See :ref:`configuration` for details.
3. Open a shell and initialize the database:
a) With docker, run the following command to open a shell within the paperless
container:
.. code:: shell-session
$ cd /path/to/paperless
$ docker-compose run --rm webserver /bin/bash
This will launch the container and initialize the PostgreSQL database.
b) Without docker, remember to activate any virtual environment, switch to
the ``src`` directory and create the database schema:
.. code:: shell-session
$ cd /path/to/paperless/src
$ python3 manage.py migrate
This will not copy any data yet.
4. Dump your data from SQLite:
.. code:: shell-session
$ python3 manage.py dumpdata --database=sqlite --exclude=contenttypes --exclude=auth.Permission > data.json
5. Load your data into PostgreSQL:
.. code:: shell-session
$ python3 manage.py loaddata data.json
6. If operating inside Docker, you may exit the shell now.
.. code:: shell-session
$ exit
7. Start paperless.
Moving back to Paperless
========================
Lets say you migrated to Paperless-ngx and used it for a while, but decided that
you don't like it and want to move back (If you do, send me a mail about what
part you didn't like!), you can totally do that with a few simple steps.
Paperless-ngx modified the database schema slightly, however, these changes can
be reverted while keeping your current data, so that your current data will
be compatible with original Paperless.
Execute this:
.. code:: shell-session
$ cd /path/to/paperless
$ docker-compose run --rm webserver migrate documents 0023
Or without docker:
.. code:: shell-session
$ cd /path/to/paperless/src
$ python3 manage.py migrate documents 0023
After that, you need to clear your cookies (Paperless-ngx comes with updated
dependencies that do cookie-processing differently) and probably your cache
as well.
.. _setup-less_powerful_devices:
Considerations for less powerful devices
########################################
Paperless runs on Raspberry Pi. However, some things are rather slow on the Pi and
configuring some options in paperless can help improve performance immensely:
* Stick with SQLite to save some resources.
* Consider setting ``PAPERLESS_OCR_PAGES`` to 1, so that paperless will only OCR
the first page of your documents. In most cases, this page contains enough
information to be able to find it.
* ``PAPERLESS_TASK_WORKERS`` and ``PAPERLESS_THREADS_PER_WORKER`` are configured
to use all cores. The Raspberry Pi models 3 and up have 4 cores, meaning that
paperless will use 2 workers and 2 threads per worker. This may result in
sluggish response times during consumption, so you might want to lower these
settings (example: 2 workers and 1 thread to always have some computing power
left for other tasks).
* Keep ``PAPERLESS_OCR_MODE`` at its default value ``skip`` and consider OCR'ing
your documents before feeding them into paperless. Some scanners are able to
do this! You might want to even specify ``skip_noarchive`` to skip archive
file generation for already ocr'ed documents entirely.
* If you want to perform OCR on the device, consider using ``PAPERLESS_OCR_CLEAN=none``.
This will speed up OCR times and use less memory at the expense of slightly worse
OCR results.
* If using docker, consider setting ``PAPERLESS_WEBSERVER_WORKERS`` to
1. This will save some memory.
* Consider setting ``PAPERLESS_ENABLE_NLTK`` to false, to disable the more
advanced language processing, which can take more memory and processing time.
For details, refer to :ref:`configuration`.
.. note::
Updating the :ref:`automatic matching algorithm <advanced-automatic_matching>`
takes quite a bit of time. However, the update mechanism checks if your
data has changed before doing the heavy lifting. If you experience the
algorithm taking too much cpu time, consider changing the schedule in the
admin interface to daily. You can also manually invoke the task
by changing the date and time of the next run to today/now.
The actual matching of the algorithm is fast and works on Raspberry Pi as
well as on any other device.
.. _redis: https://redis.io/
.. _setup-nginx:
Using nginx as a reverse proxy
##############################
If you want to expose paperless to the internet, you should hide it behind a
reverse proxy with SSL enabled.
In addition to the usual configuration for SSL,
the following configuration is required for paperless to operate:
.. code:: nginx
http {
# Adjust as required. This is the maximum size for file uploads.
# The default value 1M might be a little too small.
client_max_body_size 10M;
server {
location / {
# Adjust host and port as required.
proxy_pass http://localhost:8000/;
# These configuration options are required for WebSockets to work.
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
}
}
The ``PAPERLESS_URL`` configuration variable is also required when using a reverse proxy. Please refer to the :ref:`hosting-and-security` docs.
Also read `this <https://channels.readthedocs.io/en/stable/deploying.html#nginx-supervisor-ubuntu>`__, towards the end of the section.

335
docs/troubleshooting.md Normal file
View File

@ -0,0 +1,335 @@
# Troubleshooting
## No files are added by the consumer
Check for the following issues:
- Ensure that the directory you're putting your documents in is the
folder paperless is watching. With docker, this setting is performed
in the `docker-compose.yml` file. Without docker, look at the
`CONSUMPTION_DIR` setting. Don't adjust this setting if you're
using docker.
- Ensure that redis is up and running. Paperless does its task
processing asynchronously, and for documents to arrive at the task
processor, it needs redis to run.
- Ensure that the task processor is running. Docker does this
automatically. Manually invoke the task processor by executing
```shell-session
$ celery --app paperless worker
```
- Look at the output of paperless and inspect it for any errors.
- Go to the admin interface, and check if there are failed tasks. If
so, the tasks will contain an error message.
## Consumer warns `OCR for XX failed`
If you find the OCR accuracy to be too low, and/or the document consumer
warns that
`OCR for XX failed, but we're going to stick with what we've got since FORGIVING_OCR is enabled`,
then you might need to install the [Tesseract language
files](http://packages.ubuntu.com/search?keywords=tesseract-ocr)
marching your document's languages.
As an example, if you are running Paperless-ngx from any Ubuntu or
Debian box, and your documents are written in Spanish you may need to
run:
apt-get install -y tesseract-ocr-spa
## Consumer fails to pickup any new files
If you notice that the consumer will only pickup files in the
consumption directory at startup, but won't find any other files added
later, you will need to enable filesystem polling with the configuration
option `PAPERLESS_CONSUMER_POLLING`, see
`[here](/configuration#polling).
This will disable listening to filesystem changes with inotify and
paperless will manually check the consumption directory for changes
instead.
## Paperless always redirects to /admin
You probably had the old paperless installed at some point. Paperless
installed a permanent redirect to /admin in your browser, and you need
to clear your browsing data / cache to fix that.
## Operation not permitted
You might see errors such as:
```shell-session
chown: changing ownership of '../export': Operation not permitted
```
The container tries to set file ownership on the listed directories.
This is required so that the user running paperless inside docker has
write permissions to these folders. This happens when pointing these
directories to NFS shares, for example.
Ensure that `chown` is possible on these directories.
## Classifier error: No training data available
This indicates that the Auto matching algorithm found no documents to
learn from. This may have two reasons:
- You don't use the Auto matching algorithm: The error can be safely
ignored in this case.
- You are using the Auto matching algorithm: The classifier explicitly
excludes documents with Inbox tags. Verify that there are documents
in your archive without inbox tags. The algorithm will only learn
from documents not in your inbox.
## UserWarning in sklearn on every single document
You may encounter warnings like this:
```
/usr/local/lib/python3.7/site-packages/sklearn/base.py:315:
UserWarning: Trying to unpickle estimator CountVectorizer from version 0.23.2 when using version 0.24.0.
This might lead to breaking code or invalid results. Use at your own risk.
```
This happens when certain dependencies of paperless that are responsible
for the auto matching algorithm are updated. After updating these, your
current training data _might_ not be compatible anymore. This can be
ignored in most cases. This warning will disappear automatically when
paperless updates the training data.
If you want to get rid of the warning or actually experience issues with
automatic matching, delete the file `classification_model.pickle` in the
data directory and let paperless recreate it.
## 504 Server Error: Gateway Timeout when adding Office documents
You may experience these errors when using the optional TIKA
integration:
```
requests.exceptions.HTTPError: 504 Server Error: Gateway Timeout for url: http://gotenberg:3000/forms/libreoffice/convert
```
Gotenberg is a server that converts Office documents into PDF documents
and has a default timeout of 30 seconds. When conversion takes longer,
Gotenberg raises this error.
You can increase the timeout by configuring a command flag for Gotenberg
(see also [here](https://gotenberg.dev/docs/modules/api#properties)). If
using docker-compose, this is achieved by the following configuration
change in the `docker-compose.yml` file:
```yaml
gotenberg:
image: gotenberg/gotenberg:7.6
restart: unless-stopped
command:
- 'gotenberg'
- '--chromium-disable-routes=true'
- '--api-timeout=60'
```
## Permission denied errors in the consumption directory
You might encounter errors such as:
```shell-session
The following error occured while consuming document.pdf: [Errno 13] Permission denied: '/usr/src/paperless/src/../consume/document.pdf'
```
This happens when paperless does not have permission to delete files
inside the consumption directory. Ensure that `USERMAP_UID` and
`USERMAP_GID` are set to the user id and group id you use on the host
operating system, if these are different from `1000`. See
`setup-docker_hub`{.interpreted-text role="ref"}.
Also ensure that you are able to read and write to the consumption
directory on the host.
## OSError: \[Errno 19\] No such device when consuming files
If you experience errors such as:
```shell-session
File "/usr/local/lib/python3.7/site-packages/whoosh/codec/base.py", line 570, in open_compound_file
return CompoundStorage(dbfile, use_mmap=storage.supports_mmap)
File "/usr/local/lib/python3.7/site-packages/whoosh/filedb/compound.py", line 75, in __init__
self._source = mmap.mmap(fileno, 0, access=mmap.ACCESS_READ)
OSError: [Errno 19] No such device
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/django_q/cluster.py", line 436, in worker
res = f(*task["args"], **task["kwargs"])
File "/usr/src/paperless/src/documents/tasks.py", line 73, in consume_file
override_tag_ids=override_tag_ids)
File "/usr/src/paperless/src/documents/consumer.py", line 271, in try_consume_file
raise ConsumerError(e)
```
Paperless uses a search index to provide better and faster full text
searching. This search index is stored inside the `data` folder. The
search index uses memory-mapped files (mmap). The above error indicates
that paperless was unable to create and open these files.
This happens when you're trying to store the data directory on certain
file systems (mostly network shares) that don't support memory-mapped
files.
## Web-UI stuck at "Loading\..."
This might have multiple reasons.
1. If you built the docker image yourself or deployed using the bare
metal route, make sure that there are files in
`<paperless-root>/static/frontend/<lang-code>/`. If there are no
files, make sure that you executed `collectstatic` successfully,
either manually or as part of the docker image build.
If the front end is still missing, make sure that the front end is
compiled (files present in `src/documents/static/frontend`). If it
is not, you need to compile the front end yourself or download the
release archive instead of cloning the repository.
2. Check the output of the web server. You might see errors like this:
```
[2021-01-25 10:08:04 +0000] [40] [ERROR] Socket error processing request.
Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/gunicorn/workers/sync.py", line 134, in handle
self.handle_request(listener, req, client, addr)
File "/usr/local/lib/python3.7/site-packages/gunicorn/workers/sync.py", line 190, in handle_request
util.reraise(*sys.exc_info())
File "/usr/local/lib/python3.7/site-packages/gunicorn/util.py", line 625, in reraise
raise value
File "/usr/local/lib/python3.7/site-packages/gunicorn/workers/sync.py", line 178, in handle_request
resp.write_file(respiter)
File "/usr/local/lib/python3.7/site-packages/gunicorn/http/wsgi.py", line 396, in write_file
if not self.sendfile(respiter):
File "/usr/local/lib/python3.7/site-packages/gunicorn/http/wsgi.py", line 386, in sendfile
sent += os.sendfile(sockno, fileno, offset + sent, count)
OSError: [Errno 22] Invalid argument
```
To fix this issue, add
```
SENDFILE=0
```
to your [docker-compose.env]{.title-ref} file.
## Error while reading metadata
You might find messages like these in your log files:
```
[WARNING] [paperless.parsing.tesseract] Error while reading metadata
```
This indicates that paperless failed to read PDF metadata from one of
your documents. This happens when you open the affected documents in
paperless for editing. Paperless will continue to work, and will simply
not show the invalid metadata.
## Consumer fails with a FileNotFoundError
You might find messages like these in your log files:
```
[ERROR] [paperless.consumer] Error while consuming document SCN_0001.pdf: FileNotFoundError: [Errno 2] No such file or directory: '/tmp/ocrmypdf.io.yhk3zbv0/origin.pdf'
Traceback (most recent call last):
File "/app/paperless/src/paperless_tesseract/parsers.py", line 261, in parse
ocrmypdf.ocr(**args)
File "/usr/local/lib/python3.8/dist-packages/ocrmypdf/api.py", line 337, in ocr
return run_pipeline(options=options, plugin_manager=plugin_manager, api=True)
File "/usr/local/lib/python3.8/dist-packages/ocrmypdf/_sync.py", line 385, in run_pipeline
exec_concurrent(context, executor)
File "/usr/local/lib/python3.8/dist-packages/ocrmypdf/_sync.py", line 302, in exec_concurrent
pdf = post_process(pdf, context, executor)
File "/usr/local/lib/python3.8/dist-packages/ocrmypdf/_sync.py", line 235, in post_process
pdf_out = metadata_fixup(pdf_out, context)
File "/usr/local/lib/python3.8/dist-packages/ocrmypdf/_pipeline.py", line 798, in metadata_fixup
with pikepdf.open(context.origin) as original, pikepdf.open(working_file) as pdf:
File "/usr/local/lib/python3.8/dist-packages/pikepdf/_methods.py", line 923, in open
pdf = Pdf._open(
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/ocrmypdf.io.yhk3zbv0/origin.pdf'
```
This probably indicates paperless tried to consume the same file twice.
This can happen for a number of reasons, depending on how documents are
placed into the consume folder. If paperless is using inotify (the
default) to check for documents, try adjusting the
[inotify configuration](/configuration#inotify). If polling is enabled, try adjusting the
[polling configuration](/configuration#polling).
## Consumer fails waiting for file to remain unmodified.
You might find messages like these in your log files:
```
[ERROR] [paperless.management.consumer] Timeout while waiting on file /usr/src/paperless/src/../consume/SCN_0001.pdf to remain unmodified.
```
This indicates paperless timed out while waiting for the file to be
completely written to the consume folder. Adjusting
[polling configuration](/configuration#polling) values should resolve the issue.
!!! note
The user will need to manually move the file out of the consume folder
and back in, for the initial failing file to be consumed.
## Consumer fails reporting "OS reports file as busy still".
You might find messages like these in your log files:
```
[WARNING] [paperless.management.consumer] Not consuming file /usr/src/paperless/src/../consume/SCN_0001.pdf: OS reports file as busy still
```
This indicates paperless was unable to open the file, as the OS reported
the file as still being in use. To prevent a crash, paperless did not
try to consume the file. If paperless is using inotify (the default) to
check for documents, try adjusting the
[inotify configuration](/configuration#inotify). If polling is enabled, try adjusting the
[polling configuration](/configuration#polling).
!!! note
The user will need to manually move the file out of the consume folder
and back in, for the initial failing file to be consumed.
## Log reports "Creating PaperlessTask failed".
You might find messages like these in your log files:
```
[ERROR] [paperless.management.consumer] Creating PaperlessTask failed: db locked
```
You are likely using an sqlite based installation, with an increased
number of workers and are running into sqlite's concurrency
limitations. Uploading or consuming multiple files at once results in
many workers attempting to access the database simultaneously.
Consider changing to the PostgreSQL database if you will be processing
many documents at once often. Otherwise, try tweaking the
`PAPERLESS_DB_TIMEOUT` setting to allow more time for the database to
unlock. This may have minor performance implications.
## gunicorn fails to start with "is not a valid port number"
You are likely running using Kubernetes, which automatically creates an
environment variable named [\${serviceName}\_PORT]{.title-ref}. This is
the same environment variable which is used by Paperless to optionally
change the port gunicorn listens on.
To fix this, set [PAPERLESS_PORT]{.title-ref} again to your desired
port, or the default of 8000.

View File

@ -1,328 +0,0 @@
***************
Troubleshooting
***************
No files are added by the consumer
##################################
Check for the following issues:
* Ensure that the directory you're putting your documents in is the folder
paperless is watching. With docker, this setting is performed in the
``docker-compose.yml`` file. Without docker, look at the ``CONSUMPTION_DIR``
setting. Don't adjust this setting if you're using docker.
* Ensure that redis is up and running. Paperless does its task processing
asynchronously, and for documents to arrive at the task processor, it needs
redis to run.
* Ensure that the task processor is running. Docker does this automatically.
Manually invoke the task processor by executing
.. code:: shell-session
$ celery --app paperless worker
* Look at the output of paperless and inspect it for any errors.
* Go to the admin interface, and check if there are failed tasks. If so, the
tasks will contain an error message.
Consumer warns ``OCR for XX failed``
####################################
If you find the OCR accuracy to be too low, and/or the document consumer warns
that ``OCR for XX failed, but we're going to stick with what we've got since
FORGIVING_OCR is enabled``, then you might need to install the
`Tesseract language files <http://packages.ubuntu.com/search?keywords=tesseract-ocr>`_
marching your document's languages.
As an example, if you are running Paperless-ngx from any Ubuntu or Debian
box, and your documents are written in Spanish you may need to run::
apt-get install -y tesseract-ocr-spa
Consumer fails to pickup any new files
######################################
If you notice that the consumer will only pickup files in the consumption
directory at startup, but won't find any other files added later, you will need to
enable filesystem polling with the configuration option
``PAPERLESS_CONSUMER_POLLING``, see :ref:`here <configuration-polling>`.
This will disable listening to filesystem changes with inotify and paperless will
manually check the consumption directory for changes instead.
Paperless always redirects to /admin
####################################
You probably had the old paperless installed at some point. Paperless installed
a permanent redirect to /admin in your browser, and you need to clear your
browsing data / cache to fix that.
Operation not permitted
#######################
You might see errors such as:
.. code:: shell-session
chown: changing ownership of '../export': Operation not permitted
The container tries to set file ownership on the listed directories. This is
required so that the user running paperless inside docker has write permissions
to these folders. This happens when pointing these directories to NFS shares,
for example.
Ensure that ``chown`` is possible on these directories.
Classifier error: No training data available
############################################
This indicates that the Auto matching algorithm found no documents to learn from.
This may have two reasons:
* You don't use the Auto matching algorithm: The error can be safely ignored in this case.
* You are using the Auto matching algorithm: The classifier explicitly excludes documents
with Inbox tags. Verify that there are documents in your archive without inbox tags.
The algorithm will only learn from documents not in your inbox.
UserWarning in sklearn on every single document
###############################################
You may encounter warnings like this:
.. code::
/usr/local/lib/python3.7/site-packages/sklearn/base.py:315:
UserWarning: Trying to unpickle estimator CountVectorizer from version 0.23.2 when using version 0.24.0.
This might lead to breaking code or invalid results. Use at your own risk.
This happens when certain dependencies of paperless that are responsible for the auto matching algorithm are
updated. After updating these, your current training data *might* not be compatible anymore. This can be ignored
in most cases. This warning will disappear automatically when paperless updates the training data.
If you want to get rid of the warning or actually experience issues with automatic matching, delete
the file ``classification_model.pickle`` in the data directory and let paperless recreate it.
504 Server Error: Gateway Timeout when adding Office documents
##############################################################
You may experience these errors when using the optional TIKA integration:
.. code::
requests.exceptions.HTTPError: 504 Server Error: Gateway Timeout for url: http://gotenberg:3000/forms/libreoffice/convert
Gotenberg is a server that converts Office documents into PDF documents and has a default timeout of 30 seconds.
When conversion takes longer, Gotenberg raises this error.
You can increase the timeout by configuring a command flag for Gotenberg (see also `here <https://gotenberg.dev/docs/modules/api#properties>`__).
If using docker-compose, this is achieved by the following configuration change in the ``docker-compose.yml`` file:
.. code:: yaml
gotenberg:
image: gotenberg/gotenberg:7.6
restart: unless-stopped
command:
- "gotenberg"
- "--chromium-disable-routes=true"
- "--api-timeout=60"
Permission denied errors in the consumption directory
#####################################################
You might encounter errors such as:
.. code:: shell-session
The following error occured while consuming document.pdf: [Errno 13] Permission denied: '/usr/src/paperless/src/../consume/document.pdf'
This happens when paperless does not have permission to delete files inside the consumption directory.
Ensure that ``USERMAP_UID`` and ``USERMAP_GID`` are set to the user id and group id you use on the host operating system, if these are
different from ``1000``. See :ref:`setup-docker_hub`.
Also ensure that you are able to read and write to the consumption directory on the host.
OSError: [Errno 19] No such device when consuming files
#######################################################
If you experience errors such as:
.. code:: shell-session
File "/usr/local/lib/python3.7/site-packages/whoosh/codec/base.py", line 570, in open_compound_file
return CompoundStorage(dbfile, use_mmap=storage.supports_mmap)
File "/usr/local/lib/python3.7/site-packages/whoosh/filedb/compound.py", line 75, in __init__
self._source = mmap.mmap(fileno, 0, access=mmap.ACCESS_READ)
OSError: [Errno 19] No such device
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/django_q/cluster.py", line 436, in worker
res = f(*task["args"], **task["kwargs"])
File "/usr/src/paperless/src/documents/tasks.py", line 73, in consume_file
override_tag_ids=override_tag_ids)
File "/usr/src/paperless/src/documents/consumer.py", line 271, in try_consume_file
raise ConsumerError(e)
Paperless uses a search index to provide better and faster full text searching. This search index is stored inside
the ``data`` folder. The search index uses memory-mapped files (mmap). The above error indicates that paperless
was unable to create and open these files.
This happens when you're trying to store the data directory on certain file systems (mostly network shares)
that don't support memory-mapped files.
Web-UI stuck at "Loading..."
############################
This might have multiple reasons.
1. If you built the docker image yourself or deployed using the bare metal route,
make sure that there are files in ``<paperless-root>/static/frontend/<lang-code>/``.
If there are no files, make sure that you executed ``collectstatic`` successfully, either
manually or as part of the docker image build.
If the front end is still missing, make sure that the front end is compiled (files present in
``src/documents/static/frontend``). If it is not, you need to compile the front end yourself
or download the release archive instead of cloning the repository.
2. Check the output of the web server. You might see errors like this:
.. code::
[2021-01-25 10:08:04 +0000] [40] [ERROR] Socket error processing request.
Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/gunicorn/workers/sync.py", line 134, in handle
self.handle_request(listener, req, client, addr)
File "/usr/local/lib/python3.7/site-packages/gunicorn/workers/sync.py", line 190, in handle_request
util.reraise(*sys.exc_info())
File "/usr/local/lib/python3.7/site-packages/gunicorn/util.py", line 625, in reraise
raise value
File "/usr/local/lib/python3.7/site-packages/gunicorn/workers/sync.py", line 178, in handle_request
resp.write_file(respiter)
File "/usr/local/lib/python3.7/site-packages/gunicorn/http/wsgi.py", line 396, in write_file
if not self.sendfile(respiter):
File "/usr/local/lib/python3.7/site-packages/gunicorn/http/wsgi.py", line 386, in sendfile
sent += os.sendfile(sockno, fileno, offset + sent, count)
OSError: [Errno 22] Invalid argument
To fix this issue, add
.. code::
SENDFILE=0
to your `docker-compose.env` file.
Error while reading metadata
############################
You might find messages like these in your log files:
.. code::
[WARNING] [paperless.parsing.tesseract] Error while reading metadata
This indicates that paperless failed to read PDF metadata from one of your documents. This happens when you
open the affected documents in paperless for editing. Paperless will continue to work, and will simply not
show the invalid metadata.
Consumer fails with a FileNotFoundError
#######################################
You might find messages like these in your log files:
.. code::
[ERROR] [paperless.consumer] Error while consuming document SCN_0001.pdf: FileNotFoundError: [Errno 2] No such file or directory: '/tmp/ocrmypdf.io.yhk3zbv0/origin.pdf'
Traceback (most recent call last):
File "/app/paperless/src/paperless_tesseract/parsers.py", line 261, in parse
ocrmypdf.ocr(**args)
File "/usr/local/lib/python3.8/dist-packages/ocrmypdf/api.py", line 337, in ocr
return run_pipeline(options=options, plugin_manager=plugin_manager, api=True)
File "/usr/local/lib/python3.8/dist-packages/ocrmypdf/_sync.py", line 385, in run_pipeline
exec_concurrent(context, executor)
File "/usr/local/lib/python3.8/dist-packages/ocrmypdf/_sync.py", line 302, in exec_concurrent
pdf = post_process(pdf, context, executor)
File "/usr/local/lib/python3.8/dist-packages/ocrmypdf/_sync.py", line 235, in post_process
pdf_out = metadata_fixup(pdf_out, context)
File "/usr/local/lib/python3.8/dist-packages/ocrmypdf/_pipeline.py", line 798, in metadata_fixup
with pikepdf.open(context.origin) as original, pikepdf.open(working_file) as pdf:
File "/usr/local/lib/python3.8/dist-packages/pikepdf/_methods.py", line 923, in open
pdf = Pdf._open(
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/ocrmypdf.io.yhk3zbv0/origin.pdf'
This probably indicates paperless tried to consume the same file twice. This can happen for a number of reasons,
depending on how documents are placed into the consume folder. If paperless is using inotify (the default) to
check for documents, try adjusting the :ref:`inotify configuration <configuration-inotify>`. If polling is enabled,
try adjusting the :ref:`polling configuration <configuration-polling>`.
Consumer fails waiting for file to remain unmodified.
#####################################################
You might find messages like these in your log files:
.. code::
[ERROR] [paperless.management.consumer] Timeout while waiting on file /usr/src/paperless/src/../consume/SCN_0001.pdf to remain unmodified.
This indicates paperless timed out while waiting for the file to be completely written to the consume folder.
Adjusting :ref:`polling configuration <configuration-polling>` values should resolve the issue.
.. note::
The user will need to manually move the file out of the consume folder and
back in, for the initial failing file to be consumed.
Consumer fails reporting "OS reports file as busy still".
#########################################################
You might find messages like these in your log files:
.. code::
[WARNING] [paperless.management.consumer] Not consuming file /usr/src/paperless/src/../consume/SCN_0001.pdf: OS reports file as busy still
This indicates paperless was unable to open the file, as the OS reported the file as still being in use. To prevent a
crash, paperless did not try to consume the file. If paperless is using inotify (the default) to
check for documents, try adjusting the :ref:`inotify configuration <configuration-inotify>`. If polling is enabled,
try adjusting the :ref:`polling configuration <configuration-polling>`.
.. note::
The user will need to manually move the file out of the consume folder and
back in, for the initial failing file to be consumed.
Log reports "Creating PaperlessTask failed".
#########################################################
You might find messages like these in your log files:
.. code::
[ERROR] [paperless.management.consumer] Creating PaperlessTask failed: db locked
You are likely using an sqlite based installation, with an increased number of workers and are running into sqlite's concurrency limitations.
Uploading or consuming multiple files at once results in many workers attempting to access the database simultaneously.
Consider changing to the PostgreSQL database if you will be processing many documents at once often. Otherwise,
try tweaking the ``PAPERLESS_DB_TIMEOUT`` setting to allow more time for the database to unlock. This may have
minor performance implications.
gunicorn fails to start with "is not a valid port number"
#########################################################
You are likely running using Kubernetes, which automatically creates an environment variable named `${serviceName}_PORT`.
This is the same environment variable which is used by Paperless to optionally change the port gunicorn listens on.
To fix this, set `PAPERLESS_PORT` again to your desired port, or the default of 8000.

483
docs/usage.md Normal file
View File

@ -0,0 +1,483 @@
# Usage Overview
Paperless is an application that manages your personal documents. With
the help of a document scanner (see [the scanners wiki](https://github.com/paperless-ngx/paperless-ngx/wiki/Scanner-&-Software-Recommendations)), paperless transforms your wieldy physical document binders
into a searchable archive and provides many utilities for finding and
managing your documents.
## Terms and definitions
Paperless essentially consists of two different parts for managing your
documents:
- The _consumer_ watches a specified folder and adds all documents in
that folder to paperless.
- The _web server_ provides a UI that you use to manage and search for
your scanned documents.
Each document has a couple of fields that you can assign to them:
- A _Document_ is a piece of paper that sometimes contains valuable
information.
- The _correspondent_ of a document is the person, institution or
company that a document either originates from, or is sent to.
- A _tag_ is a label that you can assign to documents. Think of labels
as more powerful folders: Multiple documents can be grouped together
with a single tag, however, a single document can also have multiple
tags. This is not possible with folders. The reason folders are not
implemented in paperless is simply that tags are much more versatile
than folders.
- A _document type_ is used to demarcate the type of a document such
as letter, bank statement, invoice, contract, etc. It is used to
identify what a document is about.
- The _date added_ of a document is the date the document was scanned
into paperless. You cannot and should not change this date.
- The _date created_ of a document is the date the document was
initially issued. This can be the date you bought a product, the
date you signed a contract, or the date a letter was sent to you.
- The _archive serial number_ (short: ASN) of a document is the
identifier of the document in your physical document binders. See
`usage-recommended_workflow`{.interpreted-text role="ref"} below.
- The _content_ of a document is the text that was OCR'ed from the
document. This text is fed into the search engine and is used for
matching tags, correspondents and document types.
## Adding documents to paperless
Once you've got Paperless setup, you need to start feeding documents
into it. When adding documents to paperless, it will perform the
following operations on your documents:
1. OCR the document, if it has no text. Digital documents usually have
text, and this step will be skipped for those documents.
2. Paperless will create an archivable PDF/A document from your
document. If this document is coming from your scanner, it will have
embedded selectable text.
3. Paperless performs automatic matching of tags, correspondents and
types on the document before storing it in the database.
!!! tip
This process can be configured to fit your needs. If you don't want
paperless to create archived versions for digital documents, you can
configure that by configuring `PAPERLESS_OCR_MODE=skip_noarchive`.
Please read the
[relevant section in the documentation](/configuration#ocr).
!!! note
No matter which options you choose, Paperless will always store the
original document that it found in the consumption directory or in the
mail and will never overwrite that document. Archived versions are
stored alongside the original versions.
### The consumption directory
The primary method of getting documents into your database is by putting
them in the consumption directory. The consumer runs in an infinite
loop, looking for new additions to this directory. When it finds them,
the consumer goes about the process of parsing them with the OCR,
indexing what it finds, and storing it in the media directory.
Getting stuff into this directory is up to you. If you're running
Paperless on your local computer, you might just want to drag and drop
files there, but if you're running this on a server and want your
scanner to automatically push files to this directory, you'll need to
setup some sort of service to accept the files from the scanner.
Typically, you're looking at an FTP server like
[Proftpd](http://www.proftpd.org/) or a Windows folder share with
[Samba](http://www.samba.org/).
### Web UI Upload
The dashboard has a file drop field to upload documents to paperless.
Simply drag a file onto this field or select a file with the file
dialog. Multiple files are supported.
You can also upload documents on any other page of the web UI by
dragging-and-dropping files into your browser window.
### Mobile upload {#usage-mobile_upload}
The mobile app over at <https://github.com/qcasey/paperless_share>
allows Android users to share any documents with paperless. This can be
combined with any of the mobile scanning apps out there, such as Office
Lens.
Furthermore, there is the [Paperless
App](https://github.com/bauerj/paperless_app) as well, which not only
has document upload, but also document browsing and download features.
### IMAP (Email) {#usage-email}
You can tell paperless-ngx to consume documents from your email
accounts. This is a very flexible and powerful feature, if you regularly
received documents via mail that you need to archive. The mail consumer
can be configured via the frontend settings (/settings/mail) in the following
manner:
1. Define e-mail accounts.
2. Define mail rules for your account.
These rules perform the following:
1. Connect to the mail server.
2. Fetch all matching mails (as defined by folder, maximum age and the
filters)
3. Check if there are any consumable attachments.
4. If so, instruct paperless to consume the attachments and optionally
use the metadata provided in the rule for the new document.
5. If documents were consumed from a mail, the rule action is performed
on that mail.
Paperless will completely ignore mails that do not match your filters.
It will also only perform the action on mails that it has consumed
documents from.
The actions all ensure that the same mail is not consumed twice by
different means. These are as follows:
- **Delete:** Immediately deletes mail that paperless has consumed
documents from. Use with caution.
- **Mark as read:** Mark consumed mail as read. Paperless will not
consume documents from already read mails. If you read a mail before
paperless sees it, it will be ignored.
- **Flag:** Sets the 'important' flag on mails with consumed
documents. Paperless will not consume flagged mails.
- **Move to folder:** Moves consumed mails out of the way so that
paperless wont consume them again.
- **Add custom Tag:** Adds a custom tag to mails with consumed
documents (the IMAP standard calls these "keywords"). Paperless
will not consume mails already tagged. Not all mail servers support
this feature!
!!! warning
The mail consumer will perform these actions on all mails it has
consumed documents from. Keep in mind that the actual consumption
process may fail for some reason, leaving you with missing documents in
paperless.
!!! note
With the correct set of rules, you can completely automate your email
documents. Create rules for every correspondent you receive digital
documents from and paperless will read them automatically. The default
action "mark as read" is pretty tame and will not cause any damage or
data loss whatsoever.
You can also setup a special folder in your mail account for paperless
and use your favorite mail client to move to be consumed mails into that
folder automatically or manually and tell paperless to move them to yet
another folder after consumption. It's up to you.
!!! note
When defining a mail rule with a folder, you may need to try different
characters to define how the sub-folders are separated. Common values
include ".", "/" or "\|", but this varies by the mail server.
Check the documentation for your mail server. In the event of an error
fetching mail from a certain folder, check the Paperless logs. When a
folder is not located, Paperless will attempt to list all folders found
in the account to the Paperless logs.
!!! note
Paperless will process the rules in the order defined in the admin page.
You can define catch-all rules and have them executed last to consume
any documents not matched by previous rules. Such a rule may assign an
"Unknown mail document" tag to consumed documents so you can inspect
them further.
Paperless is set up to check your mails every 10 minutes. This can be
configured on the 'Scheduled tasks' page in the admin.
### REST API
You can also submit a document using the REST API, see
`api-file_uploads`{.interpreted-text role="ref"} for details.
## Best practices {#basic-searching}
Paperless offers a couple tools that help you organize your document
collection. However, it is up to you to use them in a way that helps you
organize documents and find specific documents when you need them. This
section offers a couple ideas for managing your collection.
Document types allow you to classify documents according to what they
are. You can define types such as "Receipt", "Invoice", or
"Contract". If you used to collect all your receipts in a single
binder, you can recreate that system in paperless by defining a document
type, assigning documents to that type and then filtering by that type
to only see all receipts.
Not all documents need document types. Sometimes its hard to determine
what the type of a document is or it is hard to justify creating a
document type that you only need once or twice. This is okay. As long as
the types you define help you organize your collection in the way you
want, paperless is doing its job.
Tags can be used in many different ways. Think of tags are more
versatile folders or binders. If you have a binder for documents related
to university / your car or health care, you can create these binders in
paperless by creating tags and assigning them to relevant documents.
Just as with documents, you can filter the document list by tags and
only see documents of a certain topic.
With physical documents, you'll often need to decide which folder the
document belongs to. The advantage of tags over folders and binders is
that a single document can have multiple tags. A physical document
cannot magically appear in two different folders, but with tags, this is
entirely possible.
!!! tip
This can be used in many different ways. One example: Imagine you're
working on a particular task, such as signing up for university. Usually
you'll need to collect a bunch of different documents that are already
sorted into various folders. With the tag system of paperless, you can
create a new group of documents that are relevant to this task without
destroying the already existing organization. When you're done with the
task, you could delete the tag again, which would be equal to sorting
documents back into the folder they belong into. Or keep the tag, up to
you.
All of the logic above applies to correspondents as well. Attach them to
documents if you feel that they help you organize your collection.
When you've started organizing your documents, create a couple saved
views for document collections you regularly access. This is equal to
having labeled physical binders on your desk, except that these saved
views are dynamic and simply update themselves as you add documents to
the system.
Here are a couple examples of tags and types that you could use in your
collection.
- An `inbox` tag for newly added documents that you haven't manually
edited yet.
- A tag `car` for everything car related (repairs, registration,
insurance, etc)
- A tag `todo` for documents that you still need to do something with,
such as reply, or perform some task online.
- A tag `bank account x` for all bank statement related to that
account.
- A tag `mail` for anything that you added to paperless via its mail
processing capabilities.
- A tag `missing_metadata` when you still need to add some metadata to
a document, but can't or don't want to do this right now.
## Searching {#basic-usage_searching}
Paperless offers an extensive searching mechanism that is designed to
allow you to quickly find a document you're looking for (for example,
that thing that just broke and you bought a couple months ago, that
contract you signed 8 years ago).
When you search paperless for a document, it tries to match this query
against your documents. Paperless will look for matching documents by
inspecting their content, title, correspondent, type and tags. Paperless
returns a scored list of results, so that documents matching your query
better will appear further up in the search results.
By default, paperless returns only documents which contain all words
typed in the search bar. However, paperless also offers advanced search
syntax if you want to drill down the results further.
Matching documents with logical expressions:
```
shopname AND (product1 OR product2)
```
Matching specific tags, correspondents or types:
```
type:invoice tag:unpaid
correspondent:university certificate
```
Matching dates:
```
created:[2005 to 2009]
added:yesterday
modified:today
```
Matching inexact words:
```
produ*name
```
!!! note
Inexact terms are hard for search indexes. These queries might take a
while to execute. That's why paperless offers auto complete and query
correction.
All of these constructs can be combined as you see fit. If you want to
learn more about the query language used by paperless, paperless uses
Whoosh's default query language. Head over to [Whoosh query
language](https://whoosh.readthedocs.io/en/latest/querylang.html). For
details on what date parsing utilities are available, see [Date
parsing](https://whoosh.readthedocs.io/en/latest/dates.html#parsing-date-queries).
## The recommended workflow {#usage-recommended_workflow}
Once you have familiarized yourself with paperless and are ready to use
it for all your documents, the recommended workflow for managing your
documents is as follows. This workflow also takes into account that some
documents have to be kept in physical form, but still ensures that you
get all the advantages for these documents as well.
The following diagram shows how easy it is to manage your documents.
![image](assets/recommended_workflow.png){width=400}
### Preparations in paperless
- Create an inbox tag that gets assigned to all new documents.
- Create a TODO tag.
### Processing of the physical documents
Keep a physical inbox. Whenever you receive a document that you need to
archive, put it into your inbox. Regularly, do the following for all
documents in your inbox:
1. For each document, decide if you need to keep the document in
physical form. This applies to certain important documents, such as
contracts and certificates.
2. If you need to keep the document, write a running number on the
document before scanning, starting at one and counting upwards. This
is the archive serial number, or ASN in short.
3. Scan the document.
4. If the document has an ASN assigned, store it in a _single_ binder,
sorted by ASN. Don't order this binder in any other way.
5. If the document has no ASN, throw it away. Yay!
Over time, you will notice that your physical binder will fill up. If it
is full, label the binder with the range of ASNs in this binder (i.e.,
"Documents 1 to 343"), store the binder in your cellar or elsewhere,
and start a new binder.
The idea behind this process is that you will never have to use the
physical binders to find a document. If you need a specific physical
document, you may find this document by:
1. Searching in paperless for the document.
2. Identify the ASN of the document, since it appears on the scan.
3. Grab the relevant document binder and get the document. This is easy
since they are sorted by ASN.
### Processing of documents in paperless
Once you have scanned in a document, proceed in paperless as follows.
1. If the document has an ASN, assign the ASN to the document.
2. Assign a correspondent to the document (i.e., your employer, bank,
etc) This isn't strictly necessary but helps in finding a document
when you need it.
3. Assign a document type (i.e., invoice, bank statement, etc) to the
document This isn't strictly necessary but helps in finding a
document when you need it.
4. Assign a proper title to the document (the name of an item you
bought, the subject of the letter, etc)
5. Check that the date of the document is correct. Paperless tries to
read the date from the content of the document, but this fails
sometimes if the OCR is bad or multiple dates appear on the
document.
6. Remove inbox tags from the documents.
!!! tip
You can setup manual matching rules for your correspondents and tags and
paperless will assign them automatically. After consuming a couple
documents, you can even ask paperless to *learn* when to assign tags and
correspondents by itself. For details on this feature, see
`advanced-matching`{.interpreted-text role="ref"}.
### Task management
Some documents require attention and require you to act on the document.
You may take two different approaches to handle these documents based on
how regularly you intend to scan documents and use paperless.
- If you scan and process your documents in paperless regularly,
assign a TODO tag to all scanned documents that you need to process.
Create a saved view on the dashboard that shows all documents with
this tag.
- If you do not scan documents regularly and use paperless solely for
archiving, create a physical todo box next to your physical inbox
and put documents you need to process in the TODO box. When you
performed the task associated with the document, move it to the
inbox.
## Architectue
Paperless-ngx consists of the following components:
- **The webserver:** This serves the administration pages, the API,
and the new frontend. This is the main tool you'll be using to interact
with paperless. You may start the webserver directly with
```shell-session
$ cd /path/to/paperless/src/
$ gunicorn -c ../gunicorn.conf.py paperless.wsgi
```
or by any other means such as Apache `mod_wsgi`.
- **The consumer:** This is what watches your consumption folder for
documents. However, the consumer itself does not really consume your
documents. Now it notifies a task processor that a new file is ready
for consumption. I suppose it should be named differently. This was
also used to check your emails, but that's now done elsewhere as
well.
Start the consumer with the management command `document_consumer`:
```shell-session
$ cd /path/to/paperless/src/
$ python3 manage.py document_consumer
```
- **The task processor:** Paperless relies on [Celery - Distributed
Task Queue](https://docs.celeryq.dev/en/stable/index.html) for doing
most of the heavy lifting. This is a task queue that accepts tasks
from multiple sources and processes these in parallel. It also comes
with a scheduler that executes certain commands periodically.
This task processor is responsible for:
- Consuming documents. When the consumer finds new documents, it
notifies the task processor to start a consumption task.
- The task processor also performs the consumption of any
documents you upload through the web interface.
- Consuming emails. It periodically checks your configured
accounts for new emails and notifies the task processor to
consume the attachment of an email.
- Maintaining the search index and the automatic matching
algorithm. These are things that paperless needs to do from time
to time in order to operate properly.
This allows paperless to process multiple documents from your
consumption folder in parallel! On a modern multi core system, this
makes the consumption process with full OCR blazingly fast.
The task processor comes with a built-in admin interface that you
can use to check whenever any of the tasks fail and inspect the
errors (i.e., wrong email credentials, errors during consuming a
specific file, etc).
- A [redis](https://redis.io/) message broker: This is a really
lightweight service that is responsible for getting the tasks from
the webserver and the consumer to the task scheduler. These run in a
different process (maybe even on different machines!), and
therefore, this is necessary.
- Optional: A database server. Paperless supports PostgreSQL, MariaDB
and SQLite for storing its data.

View File

@ -1,420 +0,0 @@
**************
Usage Overview
**************
Paperless is an application that manages your personal documents. With
the help of a document scanner (see :ref:`scanners`), paperless transforms
your wieldy physical document binders into a searchable archive and
provides many utilities for finding and managing your documents.
Terms and definitions
#####################
Paperless essentially consists of two different parts for managing your
documents:
* The *consumer* watches a specified folder and adds all documents in that
folder to paperless.
* The *web server* provides a UI that you use to manage and search for your
scanned documents.
Each document has a couple of fields that you can assign to them:
* A *Document* is a piece of paper that sometimes contains valuable
information.
* The *correspondent* of a document is the person, institution or company that
a document either originates from, or is sent to.
* A *tag* is a label that you can assign to documents. Think of labels as more
powerful folders: Multiple documents can be grouped together with a single
tag, however, a single document can also have multiple tags. This is not
possible with folders. The reason folders are not implemented in paperless
is simply that tags are much more versatile than folders.
* A *document type* is used to demarcate the type of a document such as letter,
bank statement, invoice, contract, etc. It is used to identify what a document
is about.
* The *date added* of a document is the date the document was scanned into
paperless. You cannot and should not change this date.
* The *date created* of a document is the date the document was initially issued.
This can be the date you bought a product, the date you signed a contract, or
the date a letter was sent to you.
* The *archive serial number* (short: ASN) of a document is the identifier of
the document in your physical document binders. See
:ref:`usage-recommended_workflow` below.
* The *content* of a document is the text that was OCR'ed from the document.
This text is fed into the search engine and is used for matching tags,
correspondents and document types.
Frontend overview
#################
.. warning::
TBD. Add some fancy screenshots!
Adding documents to paperless
#############################
Once you've got Paperless setup, you need to start feeding documents into it.
When adding documents to paperless, it will perform the following operations on
your documents:
1. OCR the document, if it has no text. Digital documents usually have text,
and this step will be skipped for those documents.
2. Paperless will create an archivable PDF/A document from your document.
If this document is coming from your scanner, it will have embedded selectable text.
3. Paperless performs automatic matching of tags, correspondents and types on the
document before storing it in the database.
.. hint::
This process can be configured to fit your needs. If you don't want paperless
to create archived versions for digital documents, you can configure that by
configuring ``PAPERLESS_OCR_MODE=skip_noarchive``. Please read the
:ref:`relevant section in the documentation <configuration-ocr>`.
.. note::
No matter which options you choose, Paperless will always store the original
document that it found in the consumption directory or in the mail and
will never overwrite that document. Archived versions are stored alongside the
original versions.
The consumption directory
=========================
The primary method of getting documents into your database is by putting them in
the consumption directory. The consumer runs in an infinite loop, looking for new
additions to this directory. When it finds them, the consumer goes about the process
of parsing them with the OCR, indexing what it finds, and storing it in the media directory.
Getting stuff into this directory is up to you. If you're running Paperless
on your local computer, you might just want to drag and drop files there, but if
you're running this on a server and want your scanner to automatically push
files to this directory, you'll need to setup some sort of service to accept the
files from the scanner. Typically, you're looking at an FTP server like
`Proftpd`_ or a Windows folder share with `Samba`_.
.. _Proftpd: http://www.proftpd.org/
.. _Samba: http://www.samba.org/
.. TODO: hyperref to configuration of the location of this magic folder.
Web UI Upload
=============
The dashboard has a file drop field to upload documents to paperless. Simply drag a file
onto this field or select a file with the file dialog. Multiple files are supported.
You can also upload documents on any other page of the web UI by dragging-and-dropping
files into your browser window.
.. _usage-mobile_upload:
Mobile upload
=============
The mobile app over at `<https://github.com/qcasey/paperless_share>`_ allows Android users
to share any documents with paperless. This can be combined with any of the mobile
scanning apps out there, such as Office Lens.
Furthermore, there is the `Paperless App <https://github.com/bauerj/paperless_app>`_ as well,
which not only has document upload, but also document browsing and download features.
.. _usage-email:
IMAP (Email)
============
You can tell paperless-ngx to consume documents from your email accounts.
This is a very flexible and powerful feature, if you regularly received documents
via mail that you need to archive. The mail consumer can be configured by using the
admin interface in the following manner:
1. Define e-mail accounts.
2. Define mail rules for your account.
These rules perform the following:
1. Connect to the mail server.
2. Fetch all matching mails (as defined by folder, maximum age and the filters)
3. Check if there are any consumable attachments.
4. If so, instruct paperless to consume the attachments and optionally
use the metadata provided in the rule for the new document.
5. If documents were consumed from a mail, the rule action is performed
on that mail.
Paperless will completely ignore mails that do not match your filters. It will also
only perform the action on mails that it has consumed documents from.
The actions all ensure that the same mail is not consumed twice by different means.
These are as follows:
* **Delete:** Immediately deletes mail that paperless has consumed documents from.
Use with caution.
* **Mark as read:** Mark consumed mail as read. Paperless will not consume documents
from already read mails. If you read a mail before paperless sees it, it will be
ignored.
* **Flag:** Sets the 'important' flag on mails with consumed documents. Paperless
will not consume flagged mails.
* **Move to folder:** Moves consumed mails out of the way so that paperless wont
consume them again.
* **Add custom Tag:** Adds a custom tag to mails with consumed documents (the IMAP
standard calls these "keywords"). Paperless will not consume mails already tagged.
Not all mail servers support this feature!
.. caution::
The mail consumer will perform these actions on all mails it has consumed
documents from. Keep in mind that the actual consumption process may fail
for some reason, leaving you with missing documents in paperless.
.. note::
With the correct set of rules, you can completely automate your email documents.
Create rules for every correspondent you receive digital documents from and
paperless will read them automatically. The default action "mark as read" is
pretty tame and will not cause any damage or data loss whatsoever.
You can also setup a special folder in your mail account for paperless and use
your favorite mail client to move to be consumed mails into that folder
automatically or manually and tell paperless to move them to yet another folder
after consumption. It's up to you.
.. note::
When defining a mail rule with a folder, you may need to try different characters to
define how the sub-folders are separated. Common values include ".", "/" or "|", but
this varies by the mail server. Check the documentation for your mail server. In the
event of an error fetching mail from a certain folder, check the Paperless logs. When
a folder is not located, Paperless will attempt to list all folders found in the account
to the Paperless logs.
.. note::
Paperless will process the rules in the order defined in the admin page.
You can define catch-all rules and have them executed last to consume
any documents not matched by previous rules. Such a rule may assign an "Unknown
mail document" tag to consumed documents so you can inspect them further.
Paperless is set up to check your mails every 10 minutes. This can be configured on the
'Scheduled tasks' page in the admin.
REST API
========
You can also submit a document using the REST API, see :ref:`api-file_uploads` for details.
.. _basic-searching:
Best practices
##############
Paperless offers a couple tools that help you organize your document collection. However,
it is up to you to use them in a way that helps you organize documents and find specific
documents when you need them. This section offers a couple ideas for managing your collection.
Document types allow you to classify documents according to what they are. You can define
types such as "Receipt", "Invoice", or "Contract". If you used to collect all your receipts
in a single binder, you can recreate that system in paperless by defining a document type,
assigning documents to that type and then filtering by that type to only see all receipts.
Not all documents need document types. Sometimes its hard to determine what the type of a
document is or it is hard to justify creating a document type that you only need once or twice.
This is okay. As long as the types you define help you organize your collection in the way
you want, paperless is doing its job.
Tags can be used in many different ways. Think of tags are more versatile folders or binders.
If you have a binder for documents related to university / your car or health care, you can
create these binders in paperless by creating tags and assigning them to relevant documents.
Just as with documents, you can filter the document list by tags and only see documents of
a certain topic.
With physical documents, you'll often need to decide which folder the document belongs to.
The advantage of tags over folders and binders is that a single document can have multiple
tags. A physical document cannot magically appear in two different folders, but with tags,
this is entirely possible.
.. hint::
This can be used in many different ways. One example: Imagine you're working on a particular
task, such as signing up for university. Usually you'll need to collect a bunch of different
documents that are already sorted into various folders. With the tag system of paperless,
you can create a new group of documents that are relevant to this task without destroying
the already existing organization. When you're done with the task, you could delete the
tag again, which would be equal to sorting documents back into the folder they belong into.
Or keep the tag, up to you.
All of the logic above applies to correspondents as well. Attach them to documents if you
feel that they help you organize your collection.
When you've started organizing your documents, create a couple saved views for document collections
you regularly access. This is equal to having labeled physical binders on your desk, except
that these saved views are dynamic and simply update themselves as you add documents to the system.
Here are a couple examples of tags and types that you could use in your collection.
* An ``inbox`` tag for newly added documents that you haven't manually edited yet.
* A tag ``car`` for everything car related (repairs, registration, insurance, etc)
* A tag ``todo`` for documents that you still need to do something with, such as reply, or
perform some task online.
* A tag ``bank account x`` for all bank statement related to that account.
* A tag ``mail`` for anything that you added to paperless via its mail processing capabilities.
* A tag ``missing_metadata`` when you still need to add some metadata to a document, but can't
or don't want to do this right now.
.. _basic-usage_searching:
Searching
#########
Paperless offers an extensive searching mechanism that is designed to allow you to quickly
find a document you're looking for (for example, that thing that just broke and you bought
a couple months ago, that contract you signed 8 years ago).
When you search paperless for a document, it tries to match this query against your documents.
Paperless will look for matching documents by inspecting their content, title, correspondent,
type and tags. Paperless returns a scored list of results, so that documents matching your query
better will appear further up in the search results.
By default, paperless returns only documents which contain all words typed in the search bar.
However, paperless also offers advanced search syntax if you want to drill down the results
further.
Matching documents with logical expressions:
.. code::
shopname AND (product1 OR product2)
Matching specific tags, correspondents or types:
.. code::
type:invoice tag:unpaid
correspondent:university certificate
Matching dates:
.. code::
created:[2005 to 2009]
added:yesterday
modified:today
Matching inexact words:
.. code::
produ*name
.. note::
Inexact terms are hard for search indexes. These queries might take a while to execute. That's why paperless offers
auto complete and query correction.
All of these constructs can be combined as you see fit.
If you want to learn more about the query language used by paperless, paperless uses Whoosh's default query language.
Head over to `Whoosh query language <https://whoosh.readthedocs.io/en/latest/querylang.html>`_.
For details on what date parsing utilities are available, see
`Date parsing <https://whoosh.readthedocs.io/en/latest/dates.html#parsing-date-queries>`_.
.. _usage-recommended_workflow:
The recommended workflow
########################
Once you have familiarized yourself with paperless and are ready to use it
for all your documents, the recommended workflow for managing your documents
is as follows. This workflow also takes into account that some documents
have to be kept in physical form, but still ensures that you get all the
advantages for these documents as well.
The following diagram shows how easy it is to manage your documents.
.. image:: _static/recommended_workflow.png
Preparations in paperless
=========================
* Create an inbox tag that gets assigned to all new documents.
* Create a TODO tag.
Processing of the physical documents
====================================
Keep a physical inbox. Whenever you receive a document that you need to
archive, put it into your inbox. Regularly, do the following for all documents
in your inbox:
1. For each document, decide if you need to keep the document in physical
form. This applies to certain important documents, such as contracts and
certificates.
2. If you need to keep the document, write a running number on the document
before scanning, starting at one and counting upwards. This is the archive
serial number, or ASN in short.
3. Scan the document.
4. If the document has an ASN assigned, store it in a *single* binder, sorted
by ASN. Don't order this binder in any other way.
5. If the document has no ASN, throw it away. Yay!
Over time, you will notice that your physical binder will fill up. If it is
full, label the binder with the range of ASNs in this binder (i.e., "Documents
1 to 343"), store the binder in your cellar or elsewhere, and start a new
binder.
The idea behind this process is that you will never have to use the physical
binders to find a document. If you need a specific physical document, you
may find this document by:
1. Searching in paperless for the document.
2. Identify the ASN of the document, since it appears on the scan.
3. Grab the relevant document binder and get the document. This is easy since
they are sorted by ASN.
Processing of documents in paperless
====================================
Once you have scanned in a document, proceed in paperless as follows.
1. If the document has an ASN, assign the ASN to the document.
2. Assign a correspondent to the document (i.e., your employer, bank, etc)
This isn't strictly necessary but helps in finding a document when you need
it.
3. Assign a document type (i.e., invoice, bank statement, etc) to the document
This isn't strictly necessary but helps in finding a document when you need
it.
4. Assign a proper title to the document (the name of an item you bought, the
subject of the letter, etc)
5. Check that the date of the document is correct. Paperless tries to read
the date from the content of the document, but this fails sometimes if the
OCR is bad or multiple dates appear on the document.
6. Remove inbox tags from the documents.
.. hint::
You can setup manual matching rules for your correspondents and tags and
paperless will assign them automatically. After consuming a couple documents,
you can even ask paperless to *learn* when to assign tags and correspondents
by itself. For details on this feature, see :ref:`advanced-matching`.
Task management
===============
Some documents require attention and require you to act on the document. You
may take two different approaches to handle these documents based on how
regularly you intend to scan documents and use paperless.
* If you scan and process your documents in paperless regularly, assign a
TODO tag to all scanned documents that you need to process. Create a saved
view on the dashboard that shows all documents with this tag.
* If you do not scan documents regularly and use paperless solely for archiving,
create a physical todo box next to your physical inbox and put documents you
need to process in the TODO box. When you performed the task associated with
the document, move it to the inbox.

60
mkdocs.yml Normal file
View File

@ -0,0 +1,60 @@
site_name: Paperless-ngx
theme:
name: material
logo: assets/logo.svg
font:
text: Roboto
code: Roboto Mono
palette:
# Palette toggle for light mode
- media: "(prefers-color-scheme: light)"
scheme: default
toggle:
icon: material/brightness-7
name: Switch to dark mode
# Palette toggle for dark mode
- media: "(prefers-color-scheme: dark)"
scheme: slate
toggle:
icon: material/brightness-4
name: Switch to light mode
features:
- navigation.tabs
- navigation.top
- toc.integrate
icon:
repo: fontawesome/brands/github
repo_url: https://github.com/paperless-ngx/paperless-ngx
extra_css:
- assets/extra.css
markdown_extensions:
- attr_list
- md_in_html
- def_list
- admonition
- tables
- pymdownx.highlight:
anchor_linenums: true
- pymdownx.superfences
nav:
- index.md
- setup.md
- 'Basic Usage': usage.md
- configuration.md
- administration.md
- advanced_usage.md
- 'REST API': api.md
- development.md
- 'FAQs': faq.md
- troubleshooting.md
- changelog.md
copyright: Copyright &copy; 2016 - 2022 Daniel Quinn, Jonas Winkler, and the Paperless-ngx team
extra:
social:
- icon: fontawesome/brands/github
link: https://github.com/paperless-ngx/paperless-ngx
- icon: fontawesome/brands/docker
link: https://hub.docker.com/r/paperlessngx/paperless-ngx
- icon: material/chat
link: https://matrix.to/#/#paperless:matrix.org