Merge branch 'dev'
commit fb9d3f736bebadd528aa47fb3a3c643f3f6d8574
Merge: 4d4d5453 049dc179
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Sun Dec 4 16:47:58 2022 -0800
    Merge pull request #2000 from paperless-ngx/feature-frontend-paperless-mail
    Feature: frontend paperless mail
commit 4d4d545343b8f44cb4377bd4292948b0a6428a87
Merge: 2704bcb9 4b31e5d0
Author: Trenton H <797416+stumpylog@users.noreply.github.com>
Date:   Sun Dec 4 16:34:41 2022 -0800
    Merge pull request #848 from p-h-a-i-l/feature-consume-eml
    Feature ability to consume mails and eml files
commit 049dc17902c11456323e3a68327963dfd3cd5f1c
Author: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
Date:   Sun Dec 4 16:33:07 2022 -0800
    Moves where the mail views live and puts the ordering on those
commit 4b31e5d0b46639c5cb68005149e2e2f0dc13ca94
Author: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
Date:   Sun Dec 4 14:00:59 2022 -0800
    Fixes my broken formatting
commit 8076ebd78ca61b8b4369ed03d462962e03b76708
Merge: fe2db4db 2704bcb9
Author: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
Date:   Sun Dec 4 13:55:46 2022 -0800
    Merge remote-tracking branch 'upstream/dev' into feature-consume-eml
commit 2704bcb979d7fa6b357f008413394f24dc950cc0
Author: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
Date:   Sun Dec 4 13:06:18 2022 -0800
    Resets to -dev versioning
commit 59f6074093e7156661044941b571a6d1fca5524f
Author: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
Date:   Sun Dec 4 12:58:03 2022 -0800
    Bumps version to 1.10.2
commit b1da7f34913fc247d1b4c333cdb98547f5816ff9
Author: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
Date:   Sun Dec 4 12:57:19 2022 -0800
    Probably fixes the changelog step not working
commit adde88e7b90ff218eff7ae98dd21eb06c945d173
Merge: a8f3c4be 8e876ef2
Author: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
Date:   Sun Dec 4 12:55:55 2022 -0800
    Merge branch 'dev'
commit 8e876ef2d15b3dd5fe055e3b389e1ccb532b2017
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sun Dec 4 10:20:48 2022 -0800
    New translations messages.xlf (Serbian (Latin))
    [ci skip]
commit 2ea0f83a91cb666710e782a53db5aba798c6f98e
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Dec 3 05:12:02 2022 -0800
    New translations messages.xlf (Italian)
    [ci skip]
commit 05d8ea5a9db8636b11e546cb2eec984126de77d0
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Dec 3 02:09:05 2022 -0800
    New translations messages.xlf (Serbian (Latin))
    [ci skip]
commit 967248233fcd1b17a0a4e0d037cd67910c666ab1
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Dec 3 02:09:04 2022 -0800
    New translations messages.xlf (French)
    [ci skip]
commit b4c4b9fb6a608473aac85f37198e0d9786d7ed39
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Dec 3 02:09:03 2022 -0800
    New translations messages.xlf (Spanish)
    [ci skip]
commit adb6483abc4d68770019a5c8b6e05db4d8ee1d82
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Dec 3 02:09:01 2022 -0800
    New translations messages.xlf (Arabic)
    [ci skip]
commit 908db55bb7545ab91af4e28db0a2b35fb9f2b490
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Dec 3 02:09:00 2022 -0800
    New translations messages.xlf (Belarusian)
    [ci skip]
commit 610f20de286f26535c0dd21b322c4c9e386a7348
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Dec 3 02:08:59 2022 -0800
    New translations messages.xlf (Czech)
    [ci skip]
commit b2513a5cde2e0b590f70d2076b8a41c906224295
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Dec 3 02:08:57 2022 -0800
    New translations messages.xlf (Danish)
    [ci skip]
commit bfa1c13d01838886b44525e8e4a444a4f8f977ab
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Dec 3 02:08:56 2022 -0800
    New translations messages.xlf (Finnish)
    [ci skip]
commit 12aaff431f64229037eefbcb93d7996787b54ddf
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Dec 3 02:08:55 2022 -0800
    New translations messages.xlf (Hebrew)
    [ci skip]
commit 547e5ea55e86548142abe348bb26b00ebaaeee9c
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Dec 3 02:08:54 2022 -0800
    New translations messages.xlf (Italian)
    [ci skip]
commit c301127096b6a70ca9f6f595ed9183ecb01dad16
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Dec 3 02:08:52 2022 -0800
    New translations messages.xlf (Dutch)
    [ci skip]
commit 19147855e715d29bce9d8c0312fd596932276409
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Dec 3 02:08:51 2022 -0800
    New translations messages.xlf (Romanian)
    [ci skip]
commit 4e7c7ea1d66be890845f899efe7c3fef2736c038
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Dec 3 02:08:49 2022 -0800
    New translations messages.xlf (Norwegian)
    [ci skip]
commit fcf8a49160702f9cb50552fefccfa20011e6bdca
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Dec 3 02:08:48 2022 -0800
    New translations messages.xlf (Portuguese)
    [ci skip]
commit c6d658a954adca50c71016305e5cf652bf7c16da
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Dec 3 02:08:47 2022 -0800
    New translations messages.xlf (Russian)
    [ci skip]
commit a78cd6526ca4955b56823fdbe1760978c1fa3e13
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Dec 3 02:08:45 2022 -0800
    New translations messages.xlf (Slovenian)
    [ci skip]
commit bf895b54f4de8ff686dd308e38fc4327437de48a
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Dec 3 02:08:44 2022 -0800
    New translations messages.xlf (Swedish)
    [ci skip]
commit e5f84ef5837508071147f01bfde5d707a1fe3588
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Dec 3 02:08:43 2022 -0800
    New translations messages.xlf (Turkish)
    [ci skip]
commit 8c690a9a51ea3f11ec9b560a544b6280f4c1b4e7
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Dec 3 02:08:41 2022 -0800
    New translations messages.xlf (Chinese Simplified)
    [ci skip]
commit 56526b970ad2539133196ac832750fee7f4dbb73
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Dec 3 02:08:40 2022 -0800
    New translations messages.xlf (Portuguese, Brazilian)
    [ci skip]
commit 94fbf929167049cd0319f89c4f9b7d017297f0c9
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Dec 3 02:08:38 2022 -0800
    New translations messages.xlf (Croatian)
    [ci skip]
commit 37f5e46d092617708578b19ef1968cd98a48a91a
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Dec 3 02:08:37 2022 -0800
    New translations messages.xlf (Luxembourgish)
    [ci skip]
commit 38be817637ebc06a6237900241ccb23110fcc5bf
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Dec 3 02:08:36 2022 -0800
    New translations messages.xlf (Polish)
    [ci skip]
commit 17303f41dadfd1ad8719a613e5e2d94284fcd492
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Dec 3 02:08:34 2022 -0800
    New translations messages.xlf (German)
    [ci skip]
commit 55ef0d4a1b62c3abe8500cad97ddeecf9f746b84
Author: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
Date:   Sun Dec 4 08:44:35 2022 -0800
    Fixes language code checks around two part languages
commit a8f3c4be5494303ed16b04ff0b4a78325302f558
Merge: fa62ae82 1b9de2be
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Sat Dec 3 18:47:09 2022 -0800
    Merge pull request #1947 from alexander-bauer/helm
    Take ownership of k8s-at-home Helm chart,
commit 1b9de2be5ab799c74953068e91c06c8fa57f5275
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Sat Dec 3 18:46:19 2022 -0800
    Use checkout v3
commit 0e8265f1aec188ea245b8a8aa4d831c95e9dd410
Merge: ea38eb01 5b45a140
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Sat Dec 3 18:44:28 2022 -0800
    Merge pull request #2109 from paperless-ngx/fix/redis-socket-parsing
    Bugfix: Redis socket compatibility didn't handle URLs with ports
commit 5b45a140b93c27b10302b2c3577fdcfd81b3a8b3
Author: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
Date:   Sat Dec 3 18:30:21 2022 -0800
    Fixes issue when the Redis URL also specifies a port
commit 72fb9a475d1f48c5e3e6ac9a057e65989a0ddbf5
Author: Alexander Bauer <sasha@linux.com>
Date:   Thu Nov 10 02:24:04 2022 +0000
    Ignore end-of-lines on generated Chart README
commit bf97f5807f6f5458ebe9d3b8336cf1b32d1f440c
Author: Alexander Bauer <sasha@linux.com>
Date:   Thu Nov 10 02:21:29 2022 +0000
    Ignore non-yaml Helm chart template
commit a707818b4da0e477026c39ddd9a2081513995d7b
Author: Alexander Bauer <sasha@linux.com>
Date:   Thu Nov 10 01:54:35 2022 +0000
    Change Helm chart releaser to use version tags only
commit fb46c1b96a1d72cc77b795df1bbbc1cbd5edfadd
Author: Alexander Bauer <sasha@linux.com>
Date:   Thu Nov 10 01:52:02 2022 +0000
    Ignore generated Helm chart README from prettier
commit 3226d8b25b7af149f8dbf69525cff9015e3676dd
Author: Alexander Bauer <sasha@linux.com>
Date:   Tue Nov 8 00:46:27 2022 +0000
    fixup! Add mostly-unchanged Helm chart from k8s-at-home
commit 5c4363cbea46630a682ed5f10bf7146f0fa24950
Author: Alexander Bauer <sasha@linux.com>
Date:   Tue Nov 8 00:24:04 2022 +0000
    Add mostly-unchanged Helm chart from k8s-at-home
    - Add the chart from k8s-at-home with some modifications
    - Add the Apache 2.0 license to the new charts/paperless-ngx
      subdirectory, the license under which the chart was distributed by
      k8s-at-home. I believe the chart will have to maintain this license.
    - Update the maintainers section and contact information to point to
      Paperless-ngx.
    - Regenerate the README (using helm-docs)
    - Add a GitHub actions configuration to publish the chart using GitHub
      pages. This makes the GitHub Pages page rendered by this repository
      usable as a Helm repository, without affecting potential future uses
      of the Pages site.
    These are in response to discussion #1790.
commit fa62ae820bdeb402f751e91f1f4d6b17b8248a21
Merge: bcc029a2 17891baf
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Sat Dec 3 14:19:36 2022 -0800
    Merge pull request #2106 from tooomm/docs/edit
    Docs: Some more small MkDocs updates
commit 17891bafaf8bd7dfcbfc949efddb6bd2d61ec62b
Author: tooomm <tooomm@users.noreply.github.com>
Date:   Sat Dec 3 20:02:40 2022 +0100
    lint
commit 15fdadadef30b40811dcac54bf9fabbde277e759
Author: tooomm <tooomm@users.noreply.github.com>
Date:   Sat Dec 3 19:36:49 2022 +0100
    open demo in new page
commit ce9f604d81820a4fba83ec38e5f58e6317165814
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Sat Dec 3 09:29:34 2022 -0800
    Explicit default ordering for rule / account views
commit 4f876db5d1d1407a8660aa1c58322fc8e36701e2
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Mon Nov 28 21:38:52 2022 -0800
    prevent loss of unsaved changes to settings on tab nav
commit 5e5f56dc67c0ba6b516a9ec7e27ca3bf653df548
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Mon Nov 28 20:39:03 2022 -0800
    Re-org where some of the new classes are found
commit 93fab8bb95661343981fbcab055de3bae9482702
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Mon Nov 28 12:53:20 2022 -0800
    Apply code suggestions from @stumpylog
commit 35ca2195feb1c32633d88da5972cc5652bc3ebf2
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Mon Nov 28 15:51:39 2022 -0800
    frontend mail rule validation
    Display non-field validation errors, hide action param field if not needed
commit 7ace66d7fd9f75ed1b66d7242622b8dee478534c
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Mon Nov 28 13:58:37 2022 -0800
    fix edit dialog getters
commit 4f9a31244b3916b7205388fcae46b2d59cca10f7
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Fri Nov 18 20:23:40 2022 -0800
    Add settings routing
commit 14cf4f709521123fcb8c9472c5f6b3c663ffc5c8
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Fri Nov 18 19:38:49 2022 -0800
    Update frontend strings
commit 8bd7c2782621c66703aff65dcf95704a83d72bf9
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Fri Nov 18 17:11:15 2022 -0800
    Hide order parameter, fix imap port
commit 8c4f486fe984e1b5ebd19e314c49ae7277ae7178
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Fri Nov 18 14:22:07 2022 -0800
    API mail rule & account tests
    and fix use of assign_tags
commit 284941444519e44b2d4322e0af2c9edd408d2b7a
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Fri Nov 18 14:21:31 2022 -0800
    one-way imap password setting via API, ObfuscatedPasswordField
commit ea1ea0816fbd4d17d9c62fe21e983f1fa62ca4d9
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Fri Nov 18 14:10:17 2022 -0800
    Fix mail account / rule delete
commit 52d3a8703c383d414298f8814a1bc3957ce89ec5
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Sat Nov 12 15:14:58 2022 -0800
    Dynamically load mail rules / accounts settings
commit 4cb4d6adcd33c917c370fd480687fdcecf09230b
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Sat Nov 12 15:15:59 2022 -0800
    update settings tests to not wait on data which is now on-demand
commit 24444237f2216ce42e1b2484de7e56296fe62a63
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Sat Nov 12 14:46:57 2022 -0800
    dynamic loading of settings tab contents
commit 40c8629aef6f0b971d17a190ad48e6c6680e4d30
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Thu Nov 10 21:04:29 2022 -0800
    Update welcome tour, move admin button
commit 98cdf614a576618a96035ff7dcc93849199ea52d
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Wed Nov 9 19:59:35 2022 -0800
    Mail form tweaks
    Include add button
    Include add button
commit 2eb2d99a913f4b1dcb8a2d55393e5e96794cb17b
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Wed Nov 9 03:43:57 2022 -0800
    Update frontend fixtures & tests for compatibility
commit 18ad9bcbf2865f27ca8a04bc37b210c9c8c3eb86
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Tue Nov 8 12:18:47 2022 -0800
    Working mail rule & account edit
commit 997bff4917d5ef8c9426d3751927b4afcf9d2e6f
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Wed Nov 9 02:40:45 2022 -0800
    Update deprecated edit-dialog rxjs
commit 78f9a8089585dd24ea53cf0ac2492de54083ecc7
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Tue Nov 8 12:09:16 2022 -0800
    mail account + rule deletion
commit 9231df7a4a9e0a4df28b11a5c4bd34fbcf9defe3
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Tue Nov 8 11:50:57 2022 -0800
    Mail rule edit dialog
commit 6f25917c86a5152ae1ec3988cd42f4dc7b76df66
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Tue Nov 8 11:11:35 2022 -0800
    Mail account edit dialog
commit c41d1a78a86d1ac585ac03e424d733087ca3fe09
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Tue Nov 8 10:53:41 2022 -0800
    remove unused toastService from edit dialogs and add confirmation
commit c3331086d55661f9f1a973194cef951d2ccd05d9
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Tue Nov 8 03:39:54 2022 -0800
    Basic data retrieval
commit 6bd9ccd8f69e163acb522833bb65b9a07763b1ce
Author: tooomm <tooomm@users.noreply.github.com>
Date:   Sat Dec 3 18:30:02 2022 +0100
    update default edit path
commit 68c7cecb07967b5fbfdc2fd0f900a938a5225b14
Author: tooomm <tooomm@users.noreply.github.com>
Date:   Sat Dec 3 18:29:14 2022 +0100
    add mkdocs site to gitignore
commit bcc029a2c763e8dcc759a815cb7332af1b90bbb9
Merge: 9d418055 1727eb00
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Sat Dec 3 09:00:02 2022 -0800
    Merge pull request #2104 from paperless-ngx/docs-cleanup
    Chore: Cleans up documentation links
commit ea38eb01b21844aadc99956b54cd3b65ffd458a1
Author: Trenton H <797416+stumpylog@users.noreply.github.com>
Date:   Fri Dec 2 13:54:15 2022 -0800
    Adds support for database number specification
commit 01d070b882ef9027bef9a046852c2060119edd5d
Author: Trenton H <797416+stumpylog@users.noreply.github.com>
Date:   Fri Dec 2 09:34:59 2022 -0800
    Adds a layer to translate between differing formats of socket based Redis URLs
commit 1727eb00cc7f98a52125a6ebdb87dad16483de3a
Author: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
Date:   Fri Dec 2 19:34:43 2022 -0800
    Cleans up a number of internal links
commit 9d4180553c972a813e4f83d4d65858c989eb20b5
Merge: 7c614264 8049af4b
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Sat Dec 3 07:58:12 2022 -0800
    Merge pull request #2102 from tooomm/patch-1
    Fix doc links in contributing
commit 8049af4b22ae1cd51d3c122eb3afd9c30beea24d
Author: tooomm <tooomm@users.noreply.github.com>
Date:   Sat Dec 3 14:38:55 2022 +0100
    Fix doc links in contributing
commit 7c6142643d054228e0902a213abdea26ff0ad063
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Sat Dec 3 02:08:51 2022 -0800
    Update more docs references
commit 2e8706f4e2fb97a70494029354c359db356c9d64
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Sat Dec 3 02:05:49 2022 -0800
    Update frontend translation strings
commit d39d32d55573d2790524db396a35ce92cfe8b695
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Sat Dec 3 02:04:30 2022 -0800
    Fix docs references
commit 6f52945449d9ddda8167597acc7d5f9165fd9d65
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Sat Dec 3 01:47:04 2022 -0800
    docs index formatting error
commit 37025297b5d03df42ac98a7b82d04f7502ab6db9
Merge: aa023ea2 dc9e9e3b
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Sat Dec 3 01:33:31 2022 -0800
    Merge pull request #2095 from paperless-ngx/update-readme-doc-links
    Documentation: Update docs links and screenshot in readme, add favicon
commit aa023ea2e355b5f40fd5d5c1f80efdb45987c09c
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Sat Dec 3 01:30:07 2022 -0800
    correct docs deploy domain
commit 78bf0b63a5ca666742970eb08704284550805e44
Merge: 29391c1c a96ecd67
Author: Felix E <felix@eckhofer.com>
Date:   Sat Dec 3 09:10:20 2022 +0100
    Merge pull request #2087 from Ricks-ha/main
    Add examples to URL and TIME_ZONE
commit dc9e9e3b48b644fb598c20e3949de09b666e31ef
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Fri Dec 2 20:06:51 2022 -0800
    add favicon
commit ab29c49b7a6855a3884ed1ffa1e00010924fc99f
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Fri Dec 2 19:09:19 2022 -0800
    Update docs links and screenshot in readme
commit 1c0ac474b85889b0c75875323734dc05b4f5ddf9
Merge: 25fb8d9c 29391c1c
Author: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
Date:   Fri Dec 2 19:05:28 2022 -0800
    Merge branch 'main' into dev
commit 29391c1c7b6c3adbd96a09d66b5a2b02e392b050
Merge: 58a01a57 69383497
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Fri Dec 2 15:22:39 2022 -0800
    Merge pull request #2067 from paperless-ngx/material-docs
    [WIP] Feature: Move docs to material-mkdocs
commit 693834971c7413098321800b150c56417e7142c6
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Thu Dec 1 20:00:23 2022 -0800
    Add v1.10.1 changelog
commit 97376d4b7229b9cdd05d151c3b61a404053c59f9
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Fri Dec 2 09:09:29 2022 -0800
    update ci for documentation build vs deploy
commit 3ee1d2a9a9a3a78e9254850f0d4a9f98664cc5dd
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Tue Nov 29 21:20:45 2022 -0800
    Add changes from #2069
commit 605f885e19136ec1c728e6c8497c0ac76eaa285e
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Tue Nov 29 12:49:23 2022 -0800
    Move docs to material-mkdocs
commit 25fb8d9c3be66e778f6215fc5c4b1377b9b526b9
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Fri Dec 2 08:30:42 2022 -0800
    Update dev version string
commit a96ecd673be07db1304d76037faec056ae170b41
Author: Ricks-ha <ricks@ricksha.eu>
Date:   Fri Dec 2 13:27:57 2022 +0100
    Add examples to URL and TIME_ZONE
commit 58a01a57ee6e018918d7b4d1d01e0d36cb351a50
Merge: a96f79f6 c18fc03e
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Fri Dec 2 03:36:55 2022 -0800
    Merge pull request #2082 from paperless-ngx/v1.10.1-changelog
    Chore: Add v1.10.1 changelong
commit c18fc03ef3c684075ec4ade333c20bc792282bfe
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Thu Dec 1 20:00:23 2022 -0800
    Add v1.10.1 changelong
commit a96f79f6a33c08d090ec33a2021996cd56df407d
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Thu Dec 1 18:54:00 2022 -0800
    Bump version to 1.10.1
commit d6f1d004a34d34b7e974393820b04d021bcca41d
Merge: 88cf6ef8 da72d357
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Thu Dec 1 18:52:35 2022 -0800
    Merge branch 'dev'
commit da72d3571be02b71ffc5650d0031e4ba2143cc78
Merge: 8241da0e 86592928
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Thu Dec 1 18:52:06 2022 -0800
    Merge pull request #2050 from paperless-ngx/l10n_dev
    New Crowdin updates
commit 8241da0eb3c1c105beecdb4204276d139a514a43
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Thu Dec 1 17:01:22 2022 -0800
    fix broken npm package-lock
commit 51562667bfe3f05e185ff878268d04af5cd63cdf
Merge: 1aee2988 97eeae65
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Thu Dec 1 16:40:07 2022 -0800
    Merge pull request #2076 from paperless-ngx/dependabot/npm_and_yarn/src-ui/dev/tslib-2.4.1
    Bump tslib from 2.4.0 to 2.4.1 in /src-ui
commit 97eeae65a3a0590a95e2ab77afd94a9ba2b48319
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Fri Dec 2 00:39:26 2022 +0000
    Bump tslib from 2.4.0 to 2.4.1 in /src-ui
    Bumps [tslib](https://github.com/Microsoft/tslib) from 2.4.0 to 2.4.1.
    - [Release notes](https://github.com/Microsoft/tslib/releases)
    - [Commits](https://github.com/Microsoft/tslib/compare/2.4.0...2.4.1)
    ---
    updated-dependencies:
    - dependency-name: tslib
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    Signed-off-by: dependabot[bot] <support@github.com>
commit 1aee2988f739634b49abcd84a31860301fb19dbd
Merge: a63a8dd4 6f0077ef
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Thu Dec 1 16:39:24 2022 -0800
    Merge pull request #2079 from paperless-ngx/dependabot/npm_and_yarn/src-ui/dev/angular-builders/jest-14.1.0
    Bump @angular-builders/jest from 14.0.1 to 14.1.0 in /src-ui
commit a63a8dd488a8af00b4783ec40a53600fe1689b42
Merge: 06a9df6d 39be68a1
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Thu Dec 1 16:38:38 2022 -0800
    Merge pull request #2078 from paperless-ngx/dependabot/npm_and_yarn/src-ui/dev/jest-preset-angular-12.2.3
    Bump jest-preset-angular from 12.2.2 to 12.2.3 in /src-ui
commit 06a9df6dbd10f7c4931a1dec4e81aee32625647d
Merge: 49933bb5 7d7d9630
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Thu Dec 1 16:37:25 2022 -0800
    Merge pull request #2080 from paperless-ngx/dependabot/npm_and_yarn/src-ui/dev/ngx-file-drop-14.0.2
    Bump ngx-file-drop from 14.0.1 to 14.0.2 in /src-ui
commit 49933bb5a82dbf143acdd004493c03a6e0b2450c
Merge: 02c782a1 ac69babf
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Thu Dec 1 16:18:07 2022 -0800
    Merge pull request #2077 from paperless-ngx/dependabot/npm_and_yarn/src-ui/dev/ngneat/dirty-check-forms-3.0.3
    Bump @ngneat/dirty-check-forms from 3.0.2 to 3.0.3 in /src-ui
commit 7d7d9630c193c119c90235751339b34142ea6dc8
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Thu Dec 1 20:03:32 2022 +0000
    Bump ngx-file-drop from 14.0.1 to 14.0.2 in /src-ui
    Bumps [ngx-file-drop](https://github.com/georgipeltekov/ngx-file-drop) from 14.0.1 to 14.0.2.
    - [Release notes](https://github.com/georgipeltekov/ngx-file-drop/releases)
    - [Changelog](https://github.com/georgipeltekov/ngx-file-drop/blob/master/CHANGELOG.md)
    - [Commits](https://github.com/georgipeltekov/ngx-file-drop/compare/v14.0.1...v14.0.2)
    ---
    updated-dependencies:
    - dependency-name: ngx-file-drop
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    Signed-off-by: dependabot[bot] <support@github.com>
commit 6f0077efac2cb8d7ecf28fa1f1cb8464f26bbb8c
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Thu Dec 1 20:03:05 2022 +0000
    Bump @angular-builders/jest from 14.0.1 to 14.1.0 in /src-ui
    Bumps [@angular-builders/jest](https://github.com/just-jeb/angular-builders/tree/HEAD/packages/jest) from 14.0.1 to 14.1.0.
    - [Release notes](https://github.com/just-jeb/angular-builders/releases)
    - [Changelog](https://github.com/just-jeb/angular-builders/blob/master/packages/jest/CHANGELOG.md)
    - [Commits](https://github.com/just-jeb/angular-builders/commits/@angular-builders/jest@14.1.0/packages/jest)
    ---
    updated-dependencies:
    - dependency-name: "@angular-builders/jest"
      dependency-type: direct:development
      update-type: version-update:semver-minor
    ...
    Signed-off-by: dependabot[bot] <support@github.com>
commit 39be68a1a4dc7a5dc7a29a416c4eb62b34f86262
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Thu Dec 1 20:02:39 2022 +0000
    Bump jest-preset-angular from 12.2.2 to 12.2.3 in /src-ui
    Bumps [jest-preset-angular](https://github.com/thymikee/jest-preset-angular) from 12.2.2 to 12.2.3.
    - [Release notes](https://github.com/thymikee/jest-preset-angular/releases)
    - [Changelog](https://github.com/thymikee/jest-preset-angular/blob/main/CHANGELOG.md)
    - [Commits](https://github.com/thymikee/jest-preset-angular/compare/v12.2.2...v12.2.3)
    ---
    updated-dependencies:
    - dependency-name: jest-preset-angular
      dependency-type: direct:development
      update-type: version-update:semver-patch
    ...
    Signed-off-by: dependabot[bot] <support@github.com>
commit ac69babfce90f55486749ce32c56bf29fba17b5e
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Thu Dec 1 20:02:11 2022 +0000
    Bump @ngneat/dirty-check-forms from 3.0.2 to 3.0.3 in /src-ui
    Bumps [@ngneat/dirty-check-forms](https://github.com/ngneat/dirty-check-forms) from 3.0.2 to 3.0.3.
    - [Release notes](https://github.com/ngneat/dirty-check-forms/releases)
    - [Changelog](https://github.com/ngneat/dirty-check-forms/blob/master/CHANGELOG.md)
    - [Commits](https://github.com/ngneat/dirty-check-forms/compare/v3.0.2...v3.0.3)
    ---
    updated-dependencies:
    - dependency-name: "@ngneat/dirty-check-forms"
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    Signed-off-by: dependabot[bot] <support@github.com>
commit 02c782a1273ff7411f53a27c3b2f4c807f4f1358
Merge: 4e90fda8 9b602a4b
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Thu Dec 1 08:19:59 2022 -0800
    Merge pull request #2073 from paperless-ngx/fix-frontend-tasks-display
    Fix: frontend tasks display in 1.10.0
commit 4e90fda80f651d67016795d8b273f34a44da880f
Author: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
Date:   Tue Nov 29 20:06:56 2022 -0800
    Expands documentation around the permissions of the custom scripts and the folder
commit 88e3e556a1ded458ea2172cbc329a3ac54470b8b
Author: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
Date:   Tue Nov 29 20:05:08 2022 -0800
    Fixes the custom scripts not running as root
commit 88cf6ef843ffe428e164f3c7c57cdf1a856c3180
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Wed Nov 30 15:14:21 2022 -0800
    add demo badge
commit 9b602a4bf016ffa6c7731269f8b3a358b1a1fba0
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Wed Nov 30 13:55:51 2022 -0800
    Fix frontend tasks display
commit fe2db4dbf7bbc21b287fd72cd124545160eaa7c0
Author: phail <phail@hacknology.de>
Date:   Wed Nov 30 10:16:39 2022 +0100
    adapt compose file for eml parsing
commit 47c88a6bdd154a343b64ca8ae5073fa58897fa7b
Merge: 4aa31859 a3bc3b78
Author: phail <phail@hacknology.de>
Date:   Wed Nov 30 10:10:57 2022 +0100
    Merge remote-tracking branch 'paperless/dev' into feature-consume-eml
commit a3bc3b78d53af7cb58456fe4b3de40258a411744
Author: Trenton H <797416+stumpylog@users.noreply.github.com>
Date:   Tue Nov 29 14:34:12 2022 -0800
    Also display the container logs
commit fed7d3e9933202c6ccdc2de7c1203a7bf2af69a0
Author: Trenton H <797416+stumpylog@users.noreply.github.com>
Date:   Tue Nov 29 13:59:48 2022 -0800
    Use docker compose to start and stop containers which match directly to our command overrides
commit 3a74f24e49e2e0aeaf17897d2fe504ae3f06377c
Author: Trenton H <797416+stumpylog@users.noreply.github.com>
Date:   Tue Nov 29 12:44:53 2022 -0800
    Adds libatomic1 for supporting armv7 better
commit 52afab39cfbd38234aa9c69cd0e1554702c0d991
Author: Trenton H <797416+stumpylog@users.noreply.github.com>
Date:   Tue Nov 29 12:16:51 2022 -0800
    Organizes the system packages a little bit more
commit 8659292852acaeb07df4a0cadc8cf09649b93961
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Tue Nov 29 00:29:45 2022 -0800
    New translations django.po (Norwegian)
    [ci skip]
commit ce73f159fd23159531c5786b381d4407c6550df9
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Mon Nov 28 14:13:54 2022 -0800
    New translations messages.xlf (Serbian (Latin))
    [ci skip]
commit 71382e9c620d25cca435a234c9a91fb7d352dab2
Merge: 5d3a6e23 a1a802fc
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Mon Nov 28 14:05:57 2022 -0800
    Merge pull request #2062 from paperless-ngx/fix/2053-long-names-too-quiet
    Bugfix: Don't silence an exception when trying to handle file naming
commit a1a802fc92359e2686497f32e53fb6247ad78886
Author: Trenton H <797416+stumpylog@users.noreply.github.com>
Date:   Mon Nov 28 13:44:17 2022 -0800
    Don't silence an exception when trying to handle file naming
commit 4200fc610dbed1a70fecbf8ade96ea8501d69e12
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Mon Nov 28 13:17:22 2022 -0800
    New translations messages.xlf (Serbian (Latin))
    [ci skip]
commit 32d212cd9f11962346f828bdb6935c522bc38a81
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Mon Nov 28 11:17:07 2022 -0800
    New translations messages.xlf (German)
    [ci skip]
commit 5d3a6e230d5e673c4ce61945098c68222b3b760f
Merge: b33fcc11 f0497e77
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Mon Nov 28 11:04:44 2022 -0800
    Merge pull request #2057 from paperless-ngx/fix/2044-lang-code-diffs
    Bugfix: Some tesseract languages aren't detected as installed.
commit b33fcc117e03b768d4fbfa7ee34470fccf2c940b
Author: Trenton H <797416+stumpylog@users.noreply.github.com>
Date:   Mon Nov 28 09:25:03 2022 -0800
    Transition to a maintained upload release assert
commit e96d65f9451a1b92aaec0085654c21a50d581adc
Author: Trenton H <797416+stumpylog@users.noreply.github.com>
Date:   Mon Nov 14 15:38:35 2022 -0800
    Allows parsing of WebP format images
commit cfeed0ce6eec797dc122d692bda7329d60d7045d
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Mon Nov 28 08:30:32 2022 -0800
    New translations django.po (Polish)
    [ci skip]
commit b89ecf7d7764c4b88c1f4caccc161c786aa306d4
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Mon Nov 28 05:28:39 2022 -0800
    New translations messages.xlf (Luxembourgish)
    [ci skip]
commit 5ca25d44baa9e086781d7c7d03bdb608839ab093
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Mon Nov 28 04:27:31 2022 -0800
    New translations messages.xlf (Luxembourgish)
    [ci skip]
commit 1e11c12d96f79b9822d96a419574b6784a41770e
Merge: e74d7dad 3e22e8e0
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Sun Nov 27 21:16:50 2022 -0800
    Merge branch 'main' into dev
commit 3e22e8e0b96a3d072c85c735639176bd5b23114f
Author: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
Date:   Sun Nov 27 19:22:59 2022 -0800
    prepends the latest changelog
commit dba45f93a4de843edba2bfb6641a14ce3f269fe4
Author: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
Date:   Sun Nov 27 19:22:03 2022 -0800
    Fixes the pre-commit command
commit 18f3f44ae918dddaed969dc563db8d7895a3148f
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sun Nov 27 17:58:25 2022 -0800
    New translations messages.xlf (Serbian (Latin))
    [ci skip]
commit 85a6a271dc9608518ae584a1a130ea32cef1aa0b
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sun Nov 27 17:58:23 2022 -0800
    New translations messages.xlf (French)
    [ci skip]
commit abb515d4ea0ef75008b6b90294185ff0b1ccb2d6
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sun Nov 27 17:58:22 2022 -0800
    New translations messages.xlf (Spanish)
    [ci skip]
commit 309d1f2b6785c9b8905aea1d28a1dc7804a712a0
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sun Nov 27 17:58:21 2022 -0800
    New translations messages.xlf (Arabic)
    [ci skip]
commit fa2f09bc4b279e22df9679ce1b6801eaa9bc9177
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sun Nov 27 17:58:19 2022 -0800
    New translations messages.xlf (Belarusian)
    [ci skip]
commit c51590cd1264835ce7cadb43b3c4c70e4712a36d
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sun Nov 27 17:58:18 2022 -0800
    New translations messages.xlf (Czech)
    [ci skip]
commit 8e01406acfed5d06b8904f68bcebe933e938ca54
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sun Nov 27 17:58:17 2022 -0800
    New translations messages.xlf (Danish)
    [ci skip]
commit 7cce2f0fe60b82c50159d25cb91bf2e87e0cc6c0
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sun Nov 27 17:58:16 2022 -0800
    New translations messages.xlf (Finnish)
    [ci skip]
commit 95091c2f393808870c91038c54036579eaa024c6
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sun Nov 27 17:58:14 2022 -0800
    New translations messages.xlf (Hebrew)
    [ci skip]
commit 4a0aa12bd99d1c99dfbf6ebf8751038f1d933169
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sun Nov 27 17:58:13 2022 -0800
    New translations messages.xlf (Italian)
    [ci skip]
commit 9a0329746a07b7307f7ddd868b4259cce38532cb
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sun Nov 27 17:58:11 2022 -0800
    New translations messages.xlf (Dutch)
    [ci skip]
commit 8392a6fd4a3777ae6d432af7c4a39e62e744511a
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sun Nov 27 17:58:10 2022 -0800
    New translations messages.xlf (Romanian)
    [ci skip]
commit 8fa18bb8a6c2065fed25f35cbb047cc1e2231979
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sun Nov 27 17:58:09 2022 -0800
    New translations messages.xlf (Norwegian)
    [ci skip]
commit 0095b593fb7ec30ce33a57931bc1c0a0ab3a87de
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sun Nov 27 17:58:08 2022 -0800
    New translations messages.xlf (Portuguese)
    [ci skip]
commit b1e5135e2126a133e1ccdb10c703996e4e20860e
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sun Nov 27 17:58:05 2022 -0800
    New translations messages.xlf (Russian)
    [ci skip]
commit e88755e7ac6b7824001ec6c7f0ca4932b9412182
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sun Nov 27 17:58:04 2022 -0800
    New translations messages.xlf (Slovenian)
    [ci skip]
commit c58294729132949a6f0b4cf0baba0bbabb60254d
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sun Nov 27 17:58:02 2022 -0800
    New translations messages.xlf (Swedish)
    [ci skip]
commit 98fe3a2cb71a2345e4c7d29eaec4428095ba5857
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sun Nov 27 17:58:01 2022 -0800
    New translations messages.xlf (Turkish)
    [ci skip]
commit 61647606fa2d571c82f93a3f0c6f50894e314f23
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sun Nov 27 17:57:59 2022 -0800
    New translations messages.xlf (Chinese Simplified)
    [ci skip]
commit 95a1e5c6454a52d446b6b88f7b9721b247558300
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sun Nov 27 17:57:58 2022 -0800
    New translations messages.xlf (Portuguese, Brazilian)
    [ci skip]
commit 8ead77f128eec14ae790bbd08880cd295a58621a
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sun Nov 27 17:57:57 2022 -0800
    New translations messages.xlf (Croatian)
    [ci skip]
commit b9e9e82f33122d4e501e906cdcb6f68131bea0cd
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sun Nov 27 17:57:55 2022 -0800
    New translations messages.xlf (Luxembourgish)
    [ci skip]
commit 487fd3a5dd4eafa8ccad1fdd7d0df0532294f273
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sun Nov 27 17:57:54 2022 -0800
    New translations messages.xlf (Polish)
    [ci skip]
commit 657786a2febe3e57b16ee021b1e968706e426a7a
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sun Nov 27 17:57:52 2022 -0800
    New translations messages.xlf (German)
    [ci skip]
commit e74d7dadfb69d5b5c7e77342cb81608a6a55845a
Author: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
Date:   Sun Nov 27 17:43:46 2022 -0800
    Adds the -dev back to the UI version
commit a2937cd54d1ceb60bcecdfa70edc19b769f01a26
Merge: 9b01aa92 7b3ce628
Author: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
Date:   Sun Nov 27 17:42:41 2022 -0800
    Merge branch 'main' into dev
commit 7b3ce6289fa2a3588ea92af9988e7ef034237c40
Author: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
Date:   Sun Nov 27 17:21:12 2022 -0800
    Bumps version number to 1.10.0
commit a16e8324bef12eed7ecab64d5b814aa514cf9b3c
Merge: 34a0111f 39de531d
Author: Trenton H <797416+stumpylog@users.noreply.github.com>
Date:   Sun Nov 27 17:18:08 2022 -0800
    Merge pull request #1960 from paperless-ngx/beta
    [Beta] Paperless-ngx v1.10.0 Release Candidate
commit 39de531df5baed7ef3b2d6eec05db0b6eb87f987
Merge: 4764d4fd c9d6c208
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Sun Nov 27 14:47:14 2022 -0800
    Merge pull request #2041 from paperless-ngx/l10n_dev
    New Crowdin updates
commit 4764d4fd2b774857d4651e71456d7c0bc3a6cc13
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Nov 26 12:28:51 2022 -0800
    New translations django.po (German)
    [ci skip]
commit e147d4571f43a47c0312c4170f62c1746543b130
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Nov 26 09:54:00 2022 -0800
    New translations django.po (German)
    [ci skip]
commit dc9aaa64727e5f1cdb9f26b8da8c34ccb822522e
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Tue Nov 22 15:21:31 2022 -0800
    New translations django.po (German)
    [ci skip]
commit 8a061c4ac219a60720d5ec6ca20aec8e13a54a10
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Tue Nov 22 15:21:30 2022 -0800
    New translations messages.xlf (German)
    [ci skip]
commit d051c5c2824dd7cf01e3a0d068264e2340e26808
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Sat Nov 12 08:48:48 2022 -0800
    Remove ar-SA
commit 9e60810a8bc3c7b570f4157080ec77a6f21ed3ba
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Nov 12 08:33:08 2022 -0800
    New translations messages.xlf (Arabic)
    [ci skip]
commit 96ee7990b2bc3ac1ebfe10d1048a4dcf697da3f1
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Fri Nov 11 13:59:54 2022 -0800
    New translations messages.xlf (Serbian (Latin))
    [ci skip]
commit 224bfeb72e18256b79afc5eff4894a30331b8090
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Fri Nov 11 13:04:01 2022 -0800
    New translations messages.xlf (Serbian (Latin))
    [ci skip]
commit f0497e77449bcb18ede3452e26fc001dfd3feaf4
Author: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
Date:   Sun Nov 27 08:28:22 2022 -0800
    Fixes how a language code like chi-sim is treated in the checks
commit c9d6c208afe5d56035cd2f10c51ed530a8371c40
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Nov 26 12:28:51 2022 -0800
    New translations django.po (German)
    [ci skip]
commit 9f2b8b1734ece2a5c51be743760098b33c9e9bfe
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Nov 26 09:54:00 2022 -0800
    New translations django.po (German)
    [ci skip]
commit a04b9e37552b7a5f4b6f26078c38fc93041d1110
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Tue Nov 22 15:21:31 2022 -0800
    New translations django.po (German)
    [ci skip]
commit a81d4c5e9dad6e8f49c20c316513cca27d99a032
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Tue Nov 22 15:21:30 2022 -0800
    New translations messages.xlf (German)
    [ci skip]
commit 2140d4209825252bd9106ac9ade6dc1ba4e507dd
Merge: a5283525 2a5dc4de
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Tue Nov 22 14:35:34 2022 -0800
    Merge pull request #2025 from paperless-ngx/fix-redo-ocr-message
    Add info that re-do OCR doesnt automatically refresh content
commit 43325371fc79726f2fbad6b00d24b4e4614fea9b
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Sat Nov 12 08:48:48 2022 -0800
    Remove ar-SA
commit d10721089e21d6a2c16f1da8b63e7e19ee22788d
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Nov 12 08:33:08 2022 -0800
    New translations messages.xlf (Arabic)
    [ci skip]
commit f1a1a2da8b89a6c30a837e8d96d8efccb678a05b
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Fri Nov 11 13:59:54 2022 -0800
    New translations messages.xlf (Serbian (Latin))
    [ci skip]
commit 612e0a1163b8fb1143108b8615097f05f0a81b15
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Fri Nov 11 13:04:01 2022 -0800
    New translations messages.xlf (Serbian (Latin))
    [ci skip]
commit 2a5dc4de3865823dca78f6042a9cbfb526950667
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Tue Nov 22 14:16:04 2022 -0800
    Add info that re-do OCR doesnt automatically refresh content
commit a5283525bc6b26f4f7b03f09ea1fe5e43cef440a
Merge: f0155565 de98d748
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Tue Nov 22 13:53:08 2022 -0800
    Merge pull request #2023 from paperless-ngx/fix/2019-create-date
    Bugfix: Fix created_date being a string
commit de98d748a9548e420be3cef3fde58eb4ce777940
Author: Trenton H <797416+stumpylog@users.noreply.github.com>
Date:   Tue Nov 22 10:11:27 2022 -0800
    If override_date is provided, coerce it into a datetime
commit f015556562ffa291f41076f49938111a674f3a60
Author: Trenton H <797416+stumpylog@users.noreply.github.com>
Date:   Mon Nov 21 14:56:14 2022 -0800
    Adds a test to cover this edge case
commit b897d6de2e3fbd26c6b6bcd9c09932e99e14fead
Author: Trenton H <797416+stumpylog@users.noreply.github.com>
Date:   Mon Nov 21 14:45:20 2022 -0800
    Don't use the sidecar file when redoing the OCR, it only contains new text
commit 54f20b381e675ddab881e16a9a8ee2181591e979
Author: Trenton H <797416+stumpylog@users.noreply.github.com>
Date:   Mon Nov 21 12:59:14 2022 -0800
    Documents some issues and the required manual fixes for MariaDB
commit c0d42480216bc4df0caed097713f960f644e4d76
Merge: 27f7f0a9 870e295a
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Mon Nov 21 22:19:02 2022 -0800
    Merge pull request #1973 from paperless-ngx/l10n_dev
    New Crowdin updates
commit 870e295aaeb0950cebed77e651df786b321c313b
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Mon Nov 21 21:43:54 2022 -0800
    New translations messages.xlf (German)
    [ci skip]
commit 4aa318598fd0dc6c5d4e08dd2a13e7bf614511ec
Author: phail <phail@hacknology.de>
Date:   Sun Nov 20 23:26:20 2022 +0100
    add test comments
commit 00f39d8b581c358f2484680275222f6ad909758c
Author: phail <phail@hacknology.de>
Date:   Sun Nov 20 22:49:42 2022 +0100
    add test comments
commit 0b1a16908fbbb88728301fa708d221a9138539ce
Author: phail <phail@hacknology.de>
Date:   Sun Nov 20 20:33:07 2022 +0100
    Include .eml reference in docs
commit d9796e5003b9a5bba80f4f1167d07524edb6aa3a
Author: phail <phail@hacknology.de>
Date:   Sun Nov 20 20:24:36 2022 +0100
    change order of elements in parsed Texts
commit 3599bb52c05a05132bedf8e641dbd2bcb1ef3410
Author: phail <phail@hacknology.de>
Date:   Sun Nov 20 20:12:41 2022 +0100
    minor test improvements
commit af8a6c3764659efa285b24ede4759aeb99eb6bcb
Author: phail <phail@hacknology.de>
Date:   Sun Nov 20 19:53:57 2022 +0100
    fix filenames
commit 6d37ebf79ea655197239982d19193c17dd534b46
Author: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
Date:   Sun Nov 20 09:15:06 2022 -0800
    Fixes one more place which used manual size formatting
commit f6a70b85f4cff8d490884a2a11ba45f44c286a98
Author: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
Date:   Sun Nov 20 09:13:08 2022 -0800
    Use Django templating engine
commit 538a4219bd951a03c403133087954ac64d4b53a2
Author: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
Date:   Sun Nov 20 09:10:44 2022 -0800
    Fixes missing return
commit 85c41b79be2033bdec5226c9687a153d7f4edc06
Author: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
Date:   Sun Nov 20 08:02:06 2022 -0800
    Adds the new packages without updating other dependencies
commit 25d014d8ef8a8dcc7f9cef0ae446eb1418ef0754
Merge: 9ec89762 27f7f0a9
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Sun Nov 20 07:48:55 2022 -0800
    Merge branch 'beta' into l10n_dev
commit 9b01aa9202ccd5ac361ab8b23ff006dcf54aa1ea
Author: Trenton H <797416+stumpylog@users.noreply.github.com>
Date:   Mon Nov 14 15:47:22 2022 -0800
    Fixes the link for flake8 to the new (?) GitHub repo
commit df101f5e7a9eb97521d752e9755806a510e12d89
Author: phail <phail@hacknology.de>
Date:   Sun Nov 20 16:09:46 2022 +0100
    split handle_message function
commit 1fa735eb23afe98d156b5ba6bf7560cc65397202
Author: phail <phail@hacknology.de>
Date:   Sun Nov 20 15:44:43 2022 +0100
    use imagehash instead of bitwise hashing
commit ebe21a01140aa5d492c34fc88be63cdfcc57b025
Author: phail <phail@hacknology.de>
Date:   Sun Nov 20 14:22:30 2022 +0100
    eml parsing requires tika
commit d132eba1431fd2c8a9dd57904cb019c26dbcc2e2
Author: phail <phail@hacknology.de>
Date:   Sun Nov 20 12:48:03 2022 +0100
    optimize regex
commit 073c3c8fed873e96a674d227f67ec96e169fbc1d
Author: phail <phail@hacknology.de>
Date:   Sun Nov 20 12:36:49 2022 +0100
    use html.escape instead of some self build functions
commit e3c1bde79334940bb70d8ed5235de85bbafc15ca
Author: phail <phail@hacknology.de>
Date:   Sun Nov 20 12:06:35 2022 +0100
    remove log mocking, replace pytest raises, use humanfriendly
commit 27f7f0a9411e85710824037d63f0e961c5a1fb4a
Merge: 9f5fd6c3 914661fd
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Thu Nov 17 14:31:46 2022 -0800
    Merge pull request #1998 from paperless-ngx/fix/1993-date-overflow
    Bugfix: Don't allow exceptions during date parsing to fail consume
commit 9f5fd6c3ba93f08d1982c33e8c861bf1164272d0
Merge: 0ae82005 3dfeee93
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Thu Nov 17 14:30:23 2022 -0800
    Merge pull request #1967 from paperless-ngx/feature-scripts-output
    Feature: Capture stdout & stderr of the pre/post consume scripts
commit 914661fdbb7adfd62481013a0bc759c920c1289d
Author: Trenton H <797416+stumpylog@users.noreply.github.com>
Date:   Thu Nov 17 13:37:37 2022 -0800
    Don't allow an exception when trying to parse a date cause complete failure
commit 0ae8200593e6c92f92004c2bf13f1e19d930775e
Author: Trenton H <797416+stumpylog@users.noreply.github.com>
Date:   Mon Nov 14 15:47:22 2022 -0800
    Fixes the link for flake8 to the new (?) GitHub repo
commit b68906b14ed89832705397b6822cf4001de87626
Author: phail <phail@hacknology.de>
Date:   Sun Nov 13 22:49:52 2022 +0100
    merge pipfile
commit 681eecc46ee042ef54f4f27b92df12685576d153
Merge: 1578e8de d4712234
Author: phail <phail@hacknology.de>
Date:   Sun Nov 13 22:43:55 2022 +0100
    Merge remote-tracking branch 'paperless/dev' into feature-consume-eml
commit 1578e8de2dab940849975b4664b329000568edc3
Author: phail <phail@hacknology.de>
Date:   Sun Nov 13 22:33:26 2022 +0100
    fix live tests
commit 023c931401db7236d2d1f10def76c1855f465917
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Sun Nov 13 07:11:45 2022 -0800
    Fix top search not working due to missing button type
commit 9ec89762a35e19e7415374e9e24c20b2d16235ac
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Nov 12 09:31:54 2022 -0800
    New translations messages.xlf (Serbian (Latin))
    [ci skip]
commit fa47595ac8b5e411bf68b72dc98f2bfb335ae6d9
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Sat Nov 12 08:58:01 2022 -0800
    remove ar_SA
    [ci skip]
commit 79f5019b40dd15effe66ef94a9ca1854908e9937
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Sat Nov 12 08:53:52 2022 -0800
    New Crowdin updates (#1971)
    * New translations messages.xlf (Serbian (Latin))
    [ci skip]
    * New translations messages.xlf (Serbian (Latin))
    [ci skip]
    * New translations messages.xlf (Italian)
    [ci skip]
    * New translations django.po (Italian)
    [ci skip]
    * New translations django.po (Serbian (Latin))
    [ci skip]
    * New translations messages.xlf (Russian)
    [ci skip]
    * New translations messages.xlf (Polish)
    [ci skip]
    * New translations messages.xlf (Serbian (Latin))
    [ci skip]
    * New translations messages.xlf (Luxembourgish)
    [ci skip]
    * New translations messages.xlf (Croatian)
    [ci skip]
    * New translations messages.xlf (Portuguese, Brazilian)
    [ci skip]
    * New translations messages.xlf (Chinese Simplified)
    [ci skip]
    * New translations messages.xlf (Turkish)
    [ci skip]
    * New translations messages.xlf (Swedish)
    [ci skip]
    * New translations messages.xlf (Slovenian)
    [ci skip]
    * New translations messages.xlf (Portuguese)
    [ci skip]
    * New translations messages.xlf (Norwegian)
    [ci skip]
    * New translations messages.xlf (German)
    [ci skip]
    * New translations messages.xlf (Dutch)
    [ci skip]
    * New translations messages.xlf (Italian)
    [ci skip]
    * New translations messages.xlf (Hebrew)
    [ci skip]
    * New translations messages.xlf (Finnish)
    [ci skip]
    * New translations messages.xlf (Danish)
    [ci skip]
    * New translations messages.xlf (Czech)
    [ci skip]
    * New translations messages.xlf (Belarusian)
    [ci skip]
    * New translations messages.xlf (Spanish)
    [ci skip]
    * New translations messages.xlf (French)
    [ci skip]
    * New translations messages.xlf (Romanian)
    [ci skip]
    * New translations messages.xlf (Arabic)
    [ci skip]
    * Remove ar-SA
    * remote ar other than ar-ar
    Co-authored-by: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
commit 756ce2f9d81a9a281e4b219999f0a35de9c536d1
Merge: 50a211f3 d4712234
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Sat Nov 12 08:33:43 2022 -0800
    Merge branch 'dev' into beta
commit d47122340a20ab429187b4bdbc74a1172da0b1dc
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Sat Nov 12 08:31:25 2022 -0800
    Add translation strings for welcome tour buttons
commit b01cbc9aa08a51a63b1719e71335d140ce73a432
Author: phail <phail@hacknology.de>
Date:   Sat Nov 12 15:48:30 2022 +0100
    add conditions to unittests
commit 3dfeee9332f4436467056178d7ddc3ff3a2aa8a8
Author: Trenton H <797416+stumpylog@users.noreply.github.com>
Date:   Fri Nov 11 10:09:56 2022 -0800
    Don't do decoding work if not needed
commit 057f6016cc92f6d21b04b9a16dc6f0b255c8b401
Author: Trenton H <797416+stumpylog@users.noreply.github.com>
Date:   Fri Nov 11 08:58:49 2022 -0800
    Adds further testing to cover scripts with non-zero exit codes
commit c4965580deebe97b40bfddaa9e0301d0ba108078
Author: Trenton H <797416+stumpylog@users.noreply.github.com>
Date:   Thu Nov 10 17:40:36 2022 -0800
    Fixes stderr appearing to have content when it doesn't
commit 9a47963fd5aa54c5bf463110603a19527a057ca3
Author: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
Date:   Wed Nov 9 20:11:36 2022 -0800
    Captures the stdout and stderr of the pre/post scripts into the log
commit 50a211f36767a3aee9f679c77ba81f41cc0dea07
Author: Trenton H <797416+stumpylog@users.noreply.github.com>
Date:   Thu Nov 10 17:25:39 2022 -0800
    Fixes an issue with the install of languages and read-only variable
commit 5f278d7fbbe1cf690a8215d59339b9cac2b7422c
Merge: e5106bdc a17d2519
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Wed Nov 9 21:37:29 2022 -0800
    Merge pull request #1956 from paperless-ngx/l10n_dev
    New Crowdin updates
commit a17d251913ac65f852aa8e80b63a306358956533
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:37 2022 -0800
    New translations django.po (Serbian (Latin))
    [ci skip]
commit 1cbf08865698a05301d88275bbad485ea325a92a
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:36 2022 -0800
    New translations messages.xlf (Serbian (Latin))
    [ci skip]
commit d3254d6bcfffc0e3abe95b86a9b1912c6616b77e
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:35 2022 -0800
    New translations messages.xlf (Luxembourgish)
    [ci skip]
commit 1543729c7be2684d47a1e7a28e8b7647f01801de
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:34 2022 -0800
    New translations messages.xlf (Croatian)
    [ci skip]
commit ef2a96c34b9de59bb0cd7f9e98b721ce3848a076
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:32 2022 -0800
    New translations messages.xlf (Portuguese, Brazilian)
    [ci skip]
commit 656b1e150ffd10527b0139ed3ea554ca6435d8c5
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:31 2022 -0800
    New translations messages.xlf (Chinese Simplified)
    [ci skip]
commit e0f61003cfeb46543bd68ccaa067977078149c35
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:30 2022 -0800
    New translations messages.xlf (Turkish)
    [ci skip]
commit 1ca98678cd592670a3366fcda0dd2fd06dda950f
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:28 2022 -0800
    New translations messages.xlf (Swedish)
    [ci skip]
commit 9919cc19567ea753552e09626795c07c45b9a737
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:27 2022 -0800
    New translations messages.xlf (Slovenian)
    [ci skip]
commit d2096e3c0593af1149f9a5395536cf309f450826
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:26 2022 -0800
    New translations messages.xlf (Portuguese)
    [ci skip]
commit 5f2b508b7a3800936fb2fbbb403a641d7550c97c
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:24 2022 -0800
    New translations messages.xlf (Polish)
    [ci skip]
commit 752d4f424900a72c92306b0151b474672b22c99d
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:23 2022 -0800
    New translations django.po (German)
    [ci skip]
commit 72e7d5150e724b63fd3ae6f34fb443375a939e04
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:22 2022 -0800
    New translations messages.xlf (Norwegian)
    [ci skip]
commit 42a9e05a7fe1fd16a471fe006f2185b6d34ed658
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:21 2022 -0800
    New translations messages.xlf (Italian)
    [ci skip]
commit b4add2ed55b346fdf3bb00dc5e4ea88457e9fbdc
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:19 2022 -0800
    New translations messages.xlf (Hebrew)
    [ci skip]
commit ed7d9295bd291626ef52a0f3f498884da04d4d3a
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:18 2022 -0800
    New translations messages.xlf (Finnish)
    [ci skip]
commit 5b7b1b2349db8daf23b3f89af865109c8fde99cc
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:16 2022 -0800
    New translations messages.xlf (Danish)
    [ci skip]
commit d5c930acc955e4ebbb5cdc6e1f35da32c99fc729
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:15 2022 -0800
    New translations messages.xlf (Czech)
    [ci skip]
commit 4c93d6d7e616c4bdb8cc205d50b918433626fc07
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:14 2022 -0800
    New translations messages.xlf (Belarusian)
    [ci skip]
commit 066f3264fbf760158c2a8d65645a86666b9f2811
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:12 2022 -0800
    New translations messages.xlf (Spanish)
    [ci skip]
commit 88a803f94950523b62cf7ea412642363fbaeb7b5
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:11 2022 -0800
    New translations messages.xlf (French)
    [ci skip]
commit e69615dc0665db8897004050ee7476df11cccbde
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:10 2022 -0800
    New translations messages.xlf (Romanian)
    [ci skip]
commit a1e0840e2486faacd3dcc492def43106922ca18d
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:08 2022 -0800
    New translations messages.xlf (Dutch)
    [ci skip]
commit d814353e830bdd442cd381fd546ed02103ce31a8
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:07 2022 -0800
    New translations messages.xlf (German)
    [ci skip]
commit 06d7845ecae8cba3bf4219ab8bf9194f6e6c3a3a
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:04 2022 -0800
    New translations django.po (Dutch)
    [ci skip]
commit ae8682c7a53d224f672aa6e2444a2b32c3e428d8
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:03 2022 -0800
    New translations django.po (Romanian)
    [ci skip]
commit c9c0b3d43031b01b38ace9ee345f97c9835964c6
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:02 2022 -0800
    New translations django.po (Luxembourgish)
    [ci skip]
commit cc46fc7e4ba09f785abb39ec9c3ef4c9109a6707
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:01 2022 -0800
    New translations django.po (Croatian)
    [ci skip]
commit d1b1ba21cd3b0b7038e62936818352c77f67a12b
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:12:00 2022 -0800
    New translations django.po (Portuguese, Brazilian)
    [ci skip]
commit a009417a996401622db2a336e94312fe7480364c
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:11:59 2022 -0800
    New translations django.po (Chinese Simplified)
    [ci skip]
commit 775da720ec5dde3562d2b01c536e0ff4ffc4351b
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:11:58 2022 -0800
    New translations django.po (Turkish)
    [ci skip]
commit aeae6ea0d349f3bbf4ebbb9b7b14652537b1a48c
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:11:57 2022 -0800
    New translations django.po (Swedish)
    [ci skip]
commit 0ae46d2269c503327071c3667946aa060c433ad8
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:11:56 2022 -0800
    New translations django.po (Slovenian)
    [ci skip]
commit 0e7f1ec0dee2a2b3513e901f3489d1f3bd564ab7
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:11:55 2022 -0800
    New translations django.po (Russian)
    [ci skip]
commit 13cd55b96fac9bd5c1b61e93fc19d4556e6b0b5a
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:11:53 2022 -0800
    New translations django.po (Portuguese)
    [ci skip]
commit 9139e807ecb7115663e1e65ac3b855c58c57ab6a
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:11:52 2022 -0800
    New translations messages.xlf (Arabic)
    [ci skip]
commit 53616f6625663d97437d781cdede1281dac5c062
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:11:51 2022 -0800
    New translations django.po (Polish)
    [ci skip]
commit 526fdf11535f87d67c88e5b02d1e9fd89e451fb2
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:11:50 2022 -0800
    New translations django.po (Italian)
    [ci skip]
commit fc4aceb0eea83800aff0c0f3bde9711e1393b79e
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:11:49 2022 -0800
    New translations django.po (Hebrew)
    [ci skip]
commit 3d8421b718e997b8b1e4913f1279847242817d70
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:11:48 2022 -0800
    New translations django.po (Finnish)
    [ci skip]
commit 6cebceda15ee35410ddb2bfbd50415cbafb4a466
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:11:47 2022 -0800
    New translations django.po (Danish)
    [ci skip]
commit e1fd6bda19fff639daa17b7273616f714af37f9f
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:11:46 2022 -0800
    New translations django.po (Czech)
    [ci skip]
commit fd34414b1725f52b9834dc6d633f4cf01666f819
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:11:45 2022 -0800
    New translations django.po (Belarusian)
    [ci skip]
commit 3ce1886a545db3d46356a65670776bc32bd6cc3c
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:11:44 2022 -0800
    New translations django.po (Arabic)
    [ci skip]
commit 8ed43779a878fb04ba47d03722ea206bc9d4340c
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:11:43 2022 -0800
    New translations django.po (Spanish)
    [ci skip]
commit a7949b3e229f3c224684ee49f8fdcafa7f7cd95f
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:11:42 2022 -0800
    New translations django.po (French)
    [ci skip]
commit 19c293c3e6d80e386699aef33c0c96de07e4300c
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:11:41 2022 -0800
    New translations django.po (Norwegian)
    [ci skip]
commit ccb1ec4ff5fec68579d3d4e173ee5fc4509d3a23
Author: Paperless-ngx Translation Bot [bot] <99855517+paperless-l10n@users.noreply.github.com>
Date:   Wed Nov 9 15:11:40 2022 -0800
    New translations messages.xlf (Russian)
    [ci skip]
commit e5106bdca0811d313a6b7894a27aa301a7b3cf90
Author: Trenton H <797416+stumpylog@users.noreply.github.com>
Date:   Wed Nov 9 14:00:09 2022 -0800
    Updates the version strings to 1.10.0
commit ba1366f49a01c7e2723e1ae4e05650e9ddae6744
Merge: 34a0111f f3b3db30
Author: Trenton H <797416+stumpylog@users.noreply.github.com>
Date:   Wed Nov 9 13:51:10 2022 -0800
    Merge branch 'dev' into beta
commit acd383241777e16e923ecceece9f2b669adb1ef3
Author: phail <phail@hacknology.de>
Date:   Thu Nov 3 21:08:15 2022 +0100
    merge Pipfile.lock
commit 82b2ba3cc2a3fb7a692f54d6c05d2395350b136f
Merge: 3de6e0bc 7e3e0a0f
Author: phail <phail@hacknology.de>
Date:   Thu Nov 3 21:00:01 2022 +0100
    Merge remote-tracking branch 'paperless/dev' into feature-consume-eml
commit 3de6e0bcf1b6e0e7afe578e37fd67f5b455c1987
Author: phail <phail@hacknology.de>
Date:   Thu Nov 3 00:58:36 2022 +0100
    put parser into setup
    make test using convert optional
    Gotenberg live testing
commit 34a0111ff5ca7dd096d69d0b4a11b97dd6121ea1
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Mon Oct 31 13:06:17 2022 -0700
    update logs section
commit b511b084d08e6e33964649f6eb1d2fadcc7cc844
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Sun Oct 30 06:48:41 2022 -0700
    Update matrix url
    [ci skip]
commit 6df73ae940420eed2b1f5c300b90992d0becb013
Author: phail <phail@hacknology.de>
Date:   Sat Oct 29 23:20:35 2022 +0200
    gotenberg with modified cmd
commit 4a24ba51c5dadf5a99e060c6147f00210c954004
Merge: 87472b31 d5fb98b7
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Fri Oct 28 22:22:08 2022 -0700
    Merge pull request #1876 from astubenbord/main
    Added new application to list of affiliated projects
commit d5fb98b7c43e607bc89602d680772d5278133a55
Author: Anton Stubenbord <79228196+astubenbord@users.noreply.github.com>
Date:   Fri Oct 28 11:07:42 2022 +0200
    Added new application to list of affiliated projects
commit 2204090151dbb34f57af8482366db1b3a4153ad8
Author: phail <phail@hacknology.de>
Date:   Thu Oct 27 23:53:47 2022 +0200
    fix string
commit 3c81a7468b47cdf5a2df0826429df99ab21f769b
Author: phail <phail@hacknology.de>
Date:   Thu Oct 27 23:41:29 2022 +0200
    replace thumbnail creation with mock
commit 5ef86f9489a43204b7ff840172a80bd0783ac260
Merge: 90cb0836 9b82ab95
Author: phail <phail@hacknology.de>
Date:   Thu Oct 27 23:12:51 2022 +0200
    Merge remote-tracking branch 'paperless/dev' into feature-consume-eml
commit 90cb0836bb5d5f06b205290c2431efa7527b7c72
Author: phail <phail@hacknology.de>
Date:   Thu Oct 27 23:11:41 2022 +0200
    Downgrade pdf validation to text only
commit ef1d4264b53d4eea2df6897c98cc31d883e35073
Author: phail <phail@hacknology.de>
Date:   Thu Oct 27 00:27:15 2022 +0200
    improve test coverage a little
commit e1fa59122dbf3224c5c5100dccee369c43a7fb8a
Merge: 5bf26369 3357fa19
Author: phail <phail@hacknology.de>
Date:   Wed Oct 26 20:59:49 2022 +0200
    Merge remote-tracking branch 'paperless/dev' into feature-consume-eml
commit 5bf26369e2b215e4418c49180c8393fc09365eea
Author: phail <phail@hacknology.de>
Date:   Tue Oct 25 21:17:40 2022 +0200
    remove erroring paramerter
commit 36239ba09f0ffc6e30cb5014f26e3edc0f7dd862
Author: phail <phail@hacknology.de>
Date:   Mon Oct 24 22:15:33 2022 +0200
    rename help text
commit 318c1d2fbd4eb9cd000ccb39dcce5eb060647eee
Merge: e7c40fc3 f8ce6285
Author: phail <phail@hacknology.de>
Date:   Mon Oct 24 21:12:35 2022 +0200
    Merge remote-tracking branch 'paperless/dev' into feature-consume-eml
commit e7c40fc3dc645d4fbe9665d82595aff71060b071
Author: phail <phail@hacknology.de>
Date:   Sun Oct 23 22:02:11 2022 +0200
    Update Pipfile
commit 0da0b1c062138ec0bc8117fcfec5cd05074ac771
Author: phail <phail@hacknology.de>
Date:   Sun Oct 23 21:39:15 2022 +0200
    update variable names
commit 08988e11f81c4db9411109cd5f48d365c9c30c11
Merge: 30372b0e 8be6c707
Author: phail <phail@hacknology.de>
Date:   Sun Oct 23 20:37:22 2022 +0200
    Merge remote-tracking branch 'paperless/dev' into feature-consume-eml
commit 30372b0e8564ab7de6986e8acd132a3b6df0ceb4
Author: phail <phail@hacknology.de>
Date:   Sun Oct 23 17:18:10 2022 +0200
    add tests for mail_to_html and generate_pdf_from_mail
commit 567e89d1c7a8fea4f66b717d3ba4cb9680fba0da
Author: phail <phail@hacknology.de>
Date:   Sat Oct 22 02:25:23 2022 +0200
    test for broken eml, add test_generate_pdf
commit f1f5227ccdbb75fff2f6af8ed1992e384939bcc5
Author: phail <phail@hacknology.de>
Date:   Sat Oct 22 00:44:32 2022 +0200
    add unittest for external images
commit 09b5bd17f2123db0679b10abd8c819b2c2a903ce
Author: phail <phail@hacknology.de>
Date:   Wed Oct 19 23:19:33 2022 +0200
    add unittest for generate_pdf_from_html
commit e384bd78c5eeb97fce8652dde24a44e71c040d39
Author: phail <phail@hacknology.de>
Date:   Tue Oct 18 23:48:07 2022 +0200
    add unittest for transform_inline_html
commit fda844f64cce6247f484dd8d14038ea36db9f934
Author: phail <phail@hacknology.de>
Date:   Sat Oct 15 15:41:43 2022 +0200
    add unittest for parse
commit daf90399bddd5cf85e25204a50860995eb55efaf
Author: phail <phail@hacknology.de>
Date:   Sat Oct 15 13:13:29 2022 +0200
    Add unitest for tika_parse()
commit 3d37e49c1a41f117518d73165311710d79045d8f
Author: phail <phail@hacknology.de>
Date:   Fri Oct 14 15:43:43 2022 +0200
    add 2 more tests
commit 261c6fb9904e5365ca5c8f61a944ffff1c448d5c
Author: phail <phail@hacknology.de>
Date:   Thu Oct 13 01:03:09 2022 +0200
    add unittest for get_thumbnail
commit 87472b31d27be1fff304377ec3260268f3ecc44d
Merge: 430c5c3b 1024d7e6
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Tue Oct 11 19:59:46 2022 -0700
    Merge pull request #1780 from paperless-ngx/fix/issue-1647
    Documentation: Add note re MS exchange servers
commit 1024d7e6e23c1fd64e29959faa97c69af53caf80
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Tue Oct 11 15:12:22 2022 -0700
    Add note re MS exchange servers
commit 430c5c3b87cab852bb556fca83dc737fc30f7c23
Merge: 0b5c6d35 b7c33550
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Fri Oct 7 23:45:51 2022 -0700
    Merge pull request #1761 from paperless-ngx/docs/lsio-tweak
    Documentation: Tweak LinuxServer
commit b7c335507ff9a38c316f1c4a727a9b2128f05069
Author: Trenton Holmes <holmes.trenton@gmail.com>
Date:   Thu Oct 6 18:24:25 2022 -0700
    Fixes the LSIO migration setting for the media root
commit 0b5c6d3532d364258f5c93ddfdcc5e8054ba0fbb
Merge: fdac108c 5fd39472
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Thu Oct 6 13:22:58 2022 -0700
    Merge pull request #1731 from paperless-ngx/fix/1624
    Documentation: Adds troubleshooting note about Kubernetes and ports
commit fdac108cab86d3d9504994f0454a7611576c45a9
Merge: 5639659b 821c14fb
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Mon Oct 3 17:07:06 2022 -0700
    Merge pull request #1733 from paperless-ngx/docs-lsio-migrate
    Documentation: LinuxServer.io Migration
commit 821c14fbce0e776e26317366c7a4e1ed0bc449d0
Author: Trenton H <holmes.trenton@gmail.com>
Date:   Mon Oct 3 11:14:18 2022 -0700
    Corrects how the link to example compose files looks
commit 8c03d9c63837a47f328711d33d154a33aae8685b
Author: Trenton H <holmes.trenton@gmail.com>
Date:   Mon Oct 3 11:11:51 2022 -0700
    Corrects a re-numbered step
commit 174a609449d4ed7d9210175d98f33407ac2f0533
Author: Trenton H <holmes.trenton@gmail.com>
Date:   Mon Oct 3 10:16:53 2022 -0700
    Adds a few steps for migration from the LinuxServer.io image
commit 5fd394726ee1718d762c71efb4203f0e66c1df54
Author: Trenton H <holmes.trenton@gmail.com>
Date:   Mon Oct 3 09:01:07 2022 -0700
    Adds troubleshooting note for Kubernetes about needing to set the port again
commit 5639659b6384fc675569fbec044bc2757a6696f5
Merge: 807b7130 7ba9cdbe
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Wed Sep 28 09:48:20 2022 -0700
    Merge pull request #1683 from paperless-ngx/fix/issue-1660
    Mariadb compose files should use `PAPERLESS_DBPASS`
commit 7ba9cdbe23365082a958856f5f52bae2908b3e14
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Wed Sep 28 09:07:30 2022 -0700
    Mariadb compose files should use `PAPERLESS_DBPASS`
commit 807b7130e5bb422d1ae418d65a9203076db262cb
Merge: 9d117ee1 e2d593c0
Author: shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Tue Sep 27 16:50:23 2022 -0700
    Merge pull request #1671 from paperless-ngx/v1.9.2-changelog
    [Documentation] Add v1.9.2 changelog
commit e2d593c023ea12853e777d70d01db201db7e38e4
Author: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date:   Tue Sep 27 10:04:41 2022 -0700
    Fix formatting, add note about 1.9.1 version string
commit 74559631244a906fe38ba050fe391d9efeb1f343
Author: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Date:   Tue Sep 27 17:01:37 2022 +0000
    Changelog  - GHA
commit cdd2b99b6b29cfb1fd8e9c3ceeb367d3237fd665
Merge: d0a0ae91 72ce4405
Author: phail <phail@hacknology.de>
Date:   Mon Jul 11 23:58:21 2022 +0200
    Merge remote-tracking branch 'paperless/dev' into feature-consume-eml
commit d0a0ae91c416cad9ccdb01fc9ed93e6f8c4214fc
Merge: c04b9fd7 feaf2da8
Author: phail <phail@hacknology.de>
Date:   Fri May 20 19:29:52 2022 +0200
    Merge branch 'dev' into feature-consume-eml
commit c04b9fd7f6a63c2889c59e0168956d89369c4876
Author: phail <phail@hacknology.de>
Date:   Thu May 19 22:51:17 2022 +0200
    switch to From: Header instead of date to compensate for older libmagic versions
commit 6809b15ce13c9d07d24a8308ed97e3b42cc5eae4
Author: phail <phail@hacknology.de>
Date:   Sat May 14 16:47:12 2022 +0200
    workaround for wrong mime detection of .eml files
commit c317eca1ca40cf94e83873112c7dede513574714
Author: phail <phel@hacknology.de>
Date:   Thu May 5 00:20:32 2022 +0200
    add attachment size to pdf
commit 466afa820352a0da59fc60b3d0e08fcc037ac11b
Author: phail <phel@hacknology.de>
Date:   Wed May 4 23:42:59 2022 +0200
    fix consumption of mails without html
    split pdf generation functions
commit c2e3dc76d94d02d86d9005d08962e9e4acff3b0c
Author: phail <phel@hacknology.de>
Date:   Tue May 3 23:21:33 2022 +0200
    add parsing of inline attachments
    remove insecure chromium option
    fix html parsing
commit 5a899664f804eb44055221b02a561ad632638158
Author: phail <phel@hacknology.de>
Date:   Tue May 3 18:02:08 2022 +0200
    remove .eml parser from tika
commit 990e905a04c78d356b0c5c3e8f53a15151af2d5d
Merge: 6b7155a8 98ebb095
Author: phail <phel@hacknology.de>
Date:   Tue May 3 17:42:56 2022 +0200
    Merge remote-tracking branch 'paperless/dev' into feature-consume-eml
commit 6b7155a8498241f707b73d5659168ac687d7d4a1
Author: phail <phel@hacknology.de>
Date:   Sat Apr 30 17:33:12 2022 +0200
    merge migrations
commit 47851ddd3f54fcddb34af370e002e927eaa431b8
Merge: 47189643 0f1e3164
Author: phail <phel@hacknology.de>
Date:   Fri Apr 29 23:52:56 2022 +0200
    Merge remote-tracking branch 'paperless/dev' into feature-consume-eml
commit 47189643ff07059e9c9c256f725bdf837c481811
Author: phail <phel@hacknology.de>
Date:   Fri Apr 29 22:58:11 2022 +0200
    add eml parser to paperless_mail
commit c1efe11cf3908aa6920e795a785451fd11c2eb71
Author: phail <phel@hacknology.de>
Date:   Wed Apr 27 23:32:10 2022 +0200
    improve pdf generation
commit 0e40ef5f352ca3e6ffe5b76374481f2a888e24dd
Author: phail <phel@hacknology.de>
Date:   Wed Apr 27 19:52:59 2022 +0200
    add css for pdf generation
commit c8081595c4450780eade4921a81d0b1bd08105cc
Author: phail <phel@hacknology.de>
Date:   Tue Apr 26 23:25:48 2022 +0200
    improve pdf generation
commit a2b5b3b2530daf7e88600d88803eb4ee43ab8dad
Author: phail <phel@hacknology.de>
Date:   Tue Apr 26 23:12:36 2022 +0200
    moved files
commit 790bcf05ed7f478dd497a8f4fcb47c10063a7859
Author: phail <phel@hacknology.de>
Date:   Mon Apr 25 20:55:00 2022 +0200
    add prototype archive pdf
commit d8d2d53c59c4902f94b9ac76f16a370662b9086e
Author: phail <phel@hacknology.de>
Date:   Tue Apr 19 20:14:31 2022 +0200
    fix Mail actions mixup
commit 027897ff0309423f524626b894981298a3606c8b
Author: phail <phel@hacknology.de>
Date:   Tue Apr 19 00:39:00 2022 +0200
    work in progress Mail parsing
commit cca576f5182fddcdeb132832fdf3fae0edfe4bfd
Author: phail <phel@hacknology.de>
Date:   Fri Apr 15 14:40:02 2022 +0200
    add feature to consume imap mail als .eml
commit 5fcf1b5434f42a55ebe4dd083d3021f27234d0cf
Author: phail <phel@hacknology.de>
Date:   Thu Apr 14 00:19:30 2022 +0200
    remove uneeded print and fix merge fail
commit 942b5aa9df53a1e0362ad4a0f65b64863829ac64
Merge: c05b39a0 cc936160
Author: phail <phel@hacknology.de>
Date:   Wed Apr 13 23:55:38 2022 +0200
    Merge branch 'dev' into fix-mail-starttls
commit c05b39a05640fa00d43de9a8c1f96f737c3a2f45
Author: phail <phel@hacknology.de>
Date:   Wed Apr 13 23:37:21 2022 +0200
    fix unittest
commit 3c8196527f73fdcbdd8da9fdc5d199184b78a254
Author: phail <phel@hacknology.de>
Date:   Sat Apr 9 13:07:14 2022 +0200
    adapt to starttls interface change in imap_tools
    pin imap-tools version to avoid breaking changes
    improve mail log
Update settings.component.ts
Update settings.component.ts
			
			
							
								
								
									
										14
									
								
								.github/ISSUE_TEMPLATE/bug-report.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						| @ -10,8 +10,8 @@ body: | |||||||
| 
 | 
 | ||||||
|         Before opening an issue, please double check: |         Before opening an issue, please double check: | ||||||
| 
 | 
 | ||||||
|         - [The troubleshooting documentation](https://paperless-ngx.readthedocs.io/en/latest/troubleshooting.html). |         - [The troubleshooting documentation](https://docs.paperless-ngx.com/troubleshooting/). | ||||||
|         - [The installation instructions](https://paperless-ngx.readthedocs.io/en/latest/setup.html#installation). |         - [The installation instructions](https://docs.paperless-ngx.com/setup/#installation). | ||||||
|         - [Existing issues and discussions](https://github.com/paperless-ngx/paperless-ngx/search?q=&type=issues). |         - [Existing issues and discussions](https://github.com/paperless-ngx/paperless-ngx/search?q=&type=issues). | ||||||
|         - Disable any customer container initialization scripts, if using any |         - Disable any customer container initialization scripts, if using any | ||||||
| 
 | 
 | ||||||
| @ -42,7 +42,15 @@ body: | |||||||
|     id: logs |     id: logs | ||||||
|     attributes: |     attributes: | ||||||
|       label: Webserver logs |       label: Webserver logs | ||||||
|       description: If available, post any logs from the web server related to your issue. |       description: Logs from the web server related to your issue. | ||||||
|  |       render: bash | ||||||
|  |     validations: | ||||||
|  |       required: true | ||||||
|  |   - type: textarea | ||||||
|  |     id: logs_browser | ||||||
|  |     attributes: | ||||||
|  |       label: Browser logs | ||||||
|  |       description: Logs from the web browser related to your issue, if needed | ||||||
|       render: bash |       render: bash | ||||||
|   - type: input |   - type: input | ||||||
|     id: version |     id: version | ||||||
|  | |||||||
							
								
								
									
										4
									
								
								.github/PULL_REQUEST_TEMPLATE.md
									
									
									
									
										vendored
									
									
								
							
							
						
						| @ -26,7 +26,7 @@ NOTE: Please check only one box! | |||||||
| 
 | 
 | ||||||
| - [ ] I have read & agree with the [contributing guidelines](https://github.com/paperless-ngx/paperless-ngx/blob/main/CONTRIBUTING.md). | - [ ] I have read & agree with the [contributing guidelines](https://github.com/paperless-ngx/paperless-ngx/blob/main/CONTRIBUTING.md). | ||||||
| - [ ] If applicable, I have tested my code for new features & regressions on both mobile & desktop devices, using the latest version of major browsers. | - [ ] If applicable, I have tested my code for new features & regressions on both mobile & desktop devices, using the latest version of major browsers. | ||||||
| - [ ] If applicable, I have checked that all tests pass, see [documentation](https://paperless-ngx.readthedocs.io/en/latest/extending.html#back-end-development). | - [ ] If applicable, I have checked that all tests pass, see [documentation](https://docs.paperless-ngx.com/development/#back-end-development). | ||||||
| - [ ] I have run all `pre-commit` hooks, see [documentation](https://paperless-ngx.readthedocs.io/en/latest/extending.html#code-formatting-with-pre-commit-hooks). | - [ ] I have run all `pre-commit` hooks, see [documentation](https://docs.paperless-ngx.com/development/#code-formatting-with-pre-commit-hooks). | ||||||
| - [ ] I have made corresponding changes to the documentation as needed. | - [ ] I have made corresponding changes to the documentation as needed. | ||||||
| - [ ] I have checked my modifications for any breaking changes. | - [ ] I have checked my modifications for any breaking changes. | ||||||
|  | |||||||
							
								
								
									
										57
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						| @ -49,7 +49,7 @@ jobs: | |||||||
|         name: Set up Python |         name: Set up Python | ||||||
|         uses: actions/setup-python@v4 |         uses: actions/setup-python@v4 | ||||||
|         with: |         with: | ||||||
|           python-version: 3.9 |           python-version: 3.8 | ||||||
|           cache: "pipenv" |           cache: "pipenv" | ||||||
|           cache-dependency-path: 'Pipfile.lock' |           cache-dependency-path: 'Pipfile.lock' | ||||||
|       - |       - | ||||||
| @ -63,14 +63,32 @@ jobs: | |||||||
|       - |       - | ||||||
|         name: Make documentation |         name: Make documentation | ||||||
|         run: | |         run: | | ||||||
|           cd docs/ |           pipenv run mkdocs build --config-file ./mkdocs.yml | ||||||
|           pipenv run make html |  | ||||||
|       - |       - | ||||||
|         name: Upload artifact |         name: Upload artifact | ||||||
|         uses: actions/upload-artifact@v3 |         uses: actions/upload-artifact@v3 | ||||||
|         with: |         with: | ||||||
|           name: documentation |           name: documentation | ||||||
|           path: docs/_build/html/ |           path: site/ | ||||||
|  | 
 | ||||||
|  |   documentation-deploy: | ||||||
|  |     name: "Deploy Documentation" | ||||||
|  |     runs-on: ubuntu-20.04 | ||||||
|  |     if: github.event_name == 'push' && github.ref == 'refs/heads/main' | ||||||
|  |     needs: | ||||||
|  |       - documentation | ||||||
|  |     steps: | ||||||
|  |       - | ||||||
|  |         name: Checkout | ||||||
|  |         uses: actions/checkout@v3 | ||||||
|  |       - | ||||||
|  |         name: Deploy docs | ||||||
|  |         uses: mhausenblas/mkdocs-deploy-gh-pages@master | ||||||
|  |         env: | ||||||
|  |           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||||
|  |           CUSTOM_DOMAIN: docs.paperless-ngx.com | ||||||
|  |           CONFIG_FILE: mkdocs.yml | ||||||
|  |           EXTRA_PACKAGES: build-base | ||||||
| 
 | 
 | ||||||
|   tests-backend: |   tests-backend: | ||||||
|     name: "Tests (${{ matrix.python-version }})" |     name: "Tests (${{ matrix.python-version }})" | ||||||
| @ -81,15 +99,6 @@ jobs: | |||||||
|       matrix: |       matrix: | ||||||
|         python-version: ['3.8', '3.9', '3.10'] |         python-version: ['3.8', '3.9', '3.10'] | ||||||
|       fail-fast: false |       fail-fast: false | ||||||
|     services: |  | ||||||
|       tika: |  | ||||||
|         image: ghcr.io/paperless-ngx/tika:latest |  | ||||||
|         ports: |  | ||||||
|           - "9998:9998/tcp" |  | ||||||
|       gotenberg: |  | ||||||
|         image: docker.io/gotenberg/gotenberg:7.6 |  | ||||||
|         ports: |  | ||||||
|           - "3000:3000/tcp" |  | ||||||
|     env: |     env: | ||||||
|       # Enable Tika end to end testing |       # Enable Tika end to end testing | ||||||
|       TIKA_LIVE: 1 |       TIKA_LIVE: 1 | ||||||
| @ -97,12 +106,21 @@ jobs: | |||||||
|       PAPERLESS_MAIL_TEST_HOST: ${{ secrets.TEST_MAIL_HOST }} |       PAPERLESS_MAIL_TEST_HOST: ${{ secrets.TEST_MAIL_HOST }} | ||||||
|       PAPERLESS_MAIL_TEST_USER: ${{ secrets.TEST_MAIL_USER }} |       PAPERLESS_MAIL_TEST_USER: ${{ secrets.TEST_MAIL_USER }} | ||||||
|       PAPERLESS_MAIL_TEST_PASSWD: ${{ secrets.TEST_MAIL_PASSWD }} |       PAPERLESS_MAIL_TEST_PASSWD: ${{ secrets.TEST_MAIL_PASSWD }} | ||||||
|  |       # Skip Tests which require convert | ||||||
|  |       PAPERLESS_TEST_SKIP_CONVERT: 1 | ||||||
|  |       # Enable Gotenberg end to end testing | ||||||
|  |       GOTENBERG_LIVE: 1 | ||||||
|     steps: |     steps: | ||||||
|       - |       - | ||||||
|         name: Checkout |         name: Checkout | ||||||
|         uses: actions/checkout@v3 |         uses: actions/checkout@v3 | ||||||
|         with: |         with: | ||||||
|           fetch-depth: 0 |           fetch-depth: 0 | ||||||
|  |       - | ||||||
|  |         name: Start containers | ||||||
|  |         run: | | ||||||
|  |           docker compose --file ${GITHUB_WORKSPACE}/docker/compose/docker-compose.ci-test.yml pull --quiet | ||||||
|  |           docker compose --file ${GITHUB_WORKSPACE}/docker/compose/docker-compose.ci-test.yml up --detach | ||||||
|       - |       - | ||||||
|         name: Install pipenv |         name: Install pipenv | ||||||
|         run: | |         run: | | ||||||
| @ -154,6 +172,12 @@ jobs: | |||||||
|         run: | |         run: | | ||||||
|           cd src/ |           cd src/ | ||||||
|           pipenv run coveralls --service=github |           pipenv run coveralls --service=github | ||||||
|  |       - | ||||||
|  |         name: Stop containers | ||||||
|  |         if: always() | ||||||
|  |         run: | | ||||||
|  |           docker compose --file ${GITHUB_WORKSPACE}/docker/compose/docker-compose.ci-test.yml logs | ||||||
|  |           docker compose --file ${GITHUB_WORKSPACE}/docker/compose/docker-compose.ci-test.yml down | ||||||
| 
 | 
 | ||||||
|   tests-frontend: |   tests-frontend: | ||||||
|     name: "Tests Frontend" |     name: "Tests Frontend" | ||||||
| @ -478,10 +502,9 @@ jobs: | |||||||
|       - |       - | ||||||
|         name: Upload release archive |         name: Upload release archive | ||||||
|         id: upload-release-asset |         id: upload-release-asset | ||||||
|         uses: actions/upload-release-asset@v1 |         uses: shogo82148/actions-upload-release-asset@v1 | ||||||
|         env: |  | ||||||
|           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |  | ||||||
|         with: |         with: | ||||||
|  |           github_token: ${{ secrets.GITHUB_TOKEN }} | ||||||
|           upload_url: ${{ steps.create-release.outputs.upload_url }} |           upload_url: ${{ steps.create-release.outputs.upload_url }} | ||||||
|           asset_path: ./paperless-ngx.tar.xz |           asset_path: ./paperless-ngx.tar.xz | ||||||
|           asset_name: paperless-ngx-${{ steps.get_version.outputs.version }}.tar.xz |           asset_name: paperless-ngx-${{ steps.get_version.outputs.version }}.tar.xz | ||||||
| @ -523,7 +546,7 @@ jobs: | |||||||
|           CURRENT_CHANGELOG=`tail --lines +2 changelog.md` |           CURRENT_CHANGELOG=`tail --lines +2 changelog.md` | ||||||
|           echo -e "$CURRENT_CHANGELOG" >> changelog-new.md |           echo -e "$CURRENT_CHANGELOG" >> changelog-new.md | ||||||
|           mv changelog-new.md changelog.md |           mv changelog-new.md changelog.md | ||||||
|           pipenv run pre-commit --files changelog.md |           pipenv run pre-commit run --files changelog.md || true | ||||||
|           git config --global user.name "github-actions" |           git config --global user.name "github-actions" | ||||||
|           git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" |           git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" | ||||||
|           git commit -am "Changelog ${{ needs.publish-release.outputs.version }} - GHA" |           git commit -am "Changelog ${{ needs.publish-release.outputs.version }} - GHA" | ||||||
|  | |||||||
							
								
								
									
										31
									
								
								.github/workflows/release-chart.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,31 @@ | |||||||
|  | --- | ||||||
|  | name: Release Charts | ||||||
|  | 
 | ||||||
|  | on: | ||||||
|  |   push: | ||||||
|  |     tags: | ||||||
|  |       - v* | ||||||
|  | 
 | ||||||
|  | jobs: | ||||||
|  |   release_chart: | ||||||
|  |     name: "Release Chart" | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     steps: | ||||||
|  |       - name: Checkout | ||||||
|  |         uses: actions/checkout@v3 | ||||||
|  |         with: | ||||||
|  |           fetch-depth: 0 | ||||||
|  | 
 | ||||||
|  |       - name: Configure Git | ||||||
|  |         run: | | ||||||
|  |           git config user.name "$GITHUB_ACTOR" | ||||||
|  |           git config user.email "$GITHUB_ACTOR@users.noreply.github.com" | ||||||
|  |       - name: Install Helm | ||||||
|  |         uses: azure/setup-helm@v3 | ||||||
|  |         with: | ||||||
|  |           version: v3.10.0 | ||||||
|  | 
 | ||||||
|  |       - name: Run chart-releaser | ||||||
|  |         uses: helm/chart-releaser-action@v1.4.1 | ||||||
|  |         env: | ||||||
|  |           CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" | ||||||
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						| @ -51,8 +51,8 @@ coverage.xml | |||||||
| # Django stuff: | # Django stuff: | ||||||
| *.log | *.log | ||||||
| 
 | 
 | ||||||
| # Sphinx documentation | # MkDocs documentation | ||||||
| docs/_build/ | site/ | ||||||
| 
 | 
 | ||||||
| # PyBuilder | # PyBuilder | ||||||
| target/ | target/ | ||||||
|  | |||||||
| @ -11,13 +11,14 @@ repos: | |||||||
|       - id: check-json |       - id: check-json | ||||||
|         exclude: "tsconfig.*json" |         exclude: "tsconfig.*json" | ||||||
|       - id: check-yaml |       - id: check-yaml | ||||||
|  |         exclude: "charts/paperless-ngx/templates/common.yaml" | ||||||
|       - id: check-toml |       - id: check-toml | ||||||
|       - id: check-executables-have-shebangs |       - id: check-executables-have-shebangs | ||||||
|       - id: end-of-file-fixer |       - id: end-of-file-fixer | ||||||
|         exclude_types: |         exclude_types: | ||||||
|           - svg |           - svg | ||||||
|           - pofile |           - pofile | ||||||
|         exclude: "(^LICENSE$)" |         exclude: "^(LICENSE|charts/paperless-ngx/README.md)$" | ||||||
|       - id: mixed-line-ending |       - id: mixed-line-ending | ||||||
|         args: |         args: | ||||||
|           - "--fix=lf" |           - "--fix=lf" | ||||||
| @ -34,7 +35,7 @@ repos: | |||||||
|           - javascript |           - javascript | ||||||
|           - ts |           - ts | ||||||
|           - markdown |           - markdown | ||||||
|         exclude: "(^Pipfile\\.lock$)" |         exclude: "(^Pipfile\\.lock$)|(^charts/paperless-ngx/README.md$)" | ||||||
|   # Python hooks |   # Python hooks | ||||||
|   - repo: https://github.com/asottile/reorder_python_imports |   - repo: https://github.com/asottile/reorder_python_imports | ||||||
|     rev: v3.9.0 |     rev: v3.9.0 | ||||||
|  | |||||||
| @ -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 |  | ||||||
| @ -27,11 +27,11 @@ Please format and test your code! I know it's a hassle, but it makes sure that y | |||||||
| 
 | 
 | ||||||
| To test your code, execute `pytest` in the src/ directory. This also generates a html coverage report, which you can use to see if you missed anything important during testing. | To test your code, execute `pytest` in the src/ directory. This also generates a html coverage report, which you can use to see if you missed anything important during testing. | ||||||
| 
 | 
 | ||||||
| Before you can run `pytest`, ensure to [properly set up your local environment](https://paperless-ngx.readthedocs.io/en/latest/extending.html#initial-setup-and-first-start). | Before you can run `pytest`, ensure to [properly set up your local environment](https://docs.paperless-ngx.com/development/#initial-setup-and-first-start). | ||||||
| 
 | 
 | ||||||
| ## More info: | ## More info: | ||||||
| 
 | 
 | ||||||
| ... is available in the documentation. https://paperless-ngx.readthedocs.io/en/latest/extending.html | ... is available [in the documentation](https://docs.paperless-ngx.com/development). | ||||||
| 
 | 
 | ||||||
| # Merging PRs | # Merging PRs | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										43
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						| @ -52,7 +52,7 @@ RUN set -eux \ | |||||||
| FROM python:3.9-slim-bullseye as main-app | FROM python:3.9-slim-bullseye as main-app | ||||||
| 
 | 
 | ||||||
| LABEL org.opencontainers.image.authors="paperless-ngx team <hello@paperless-ngx.com>" | LABEL org.opencontainers.image.authors="paperless-ngx team <hello@paperless-ngx.com>" | ||||||
| LABEL org.opencontainers.image.documentation="https://paperless-ngx.readthedocs.io/en/latest/" | LABEL org.opencontainers.image.documentation="https://docs.paperless-ngx.com/" | ||||||
| LABEL org.opencontainers.image.source="https://github.com/paperless-ngx/paperless-ngx" | LABEL org.opencontainers.image.source="https://github.com/paperless-ngx/paperless-ngx" | ||||||
| LABEL org.opencontainers.image.url="https://github.com/paperless-ngx/paperless-ngx" | LABEL org.opencontainers.image.url="https://github.com/paperless-ngx/paperless-ngx" | ||||||
| LABEL org.opencontainers.image.licenses="GPL-3.0-only" | LABEL org.opencontainers.image.licenses="GPL-3.0-only" | ||||||
| @ -72,34 +72,37 @@ COPY --from=jbig2enc-builder /usr/src/jbig2enc/src/*.h /usr/local/include/ | |||||||
| 
 | 
 | ||||||
| # Packages need for running | # Packages need for running | ||||||
| ARG RUNTIME_PACKAGES="\ | ARG RUNTIME_PACKAGES="\ | ||||||
|  |   # Python | ||||||
|  |   python3 \ | ||||||
|  |   python3-pip \ | ||||||
|  |   python3-setuptools \ | ||||||
|  |   # General utils | ||||||
|   curl \ |   curl \ | ||||||
|   file \ |   # Docker specific | ||||||
|  |   gosu \ | ||||||
|  |   # Timezones support | ||||||
|  |   tzdata \ | ||||||
|   # fonts for text file thumbnail generation |   # fonts for text file thumbnail generation | ||||||
|   fonts-liberation \ |   fonts-liberation \ | ||||||
|   gettext \ |   gettext \ | ||||||
|   ghostscript \ |   ghostscript \ | ||||||
|   gnupg \ |   gnupg \ | ||||||
|   gosu \ |  | ||||||
|   icc-profiles-free \ |   icc-profiles-free \ | ||||||
|   imagemagick \ |   imagemagick \ | ||||||
|   media-types \ |   # Image processing | ||||||
|   liblept5 \ |   liblept5 \ | ||||||
|   libpq5 \ |  | ||||||
|   libxml2 \ |  | ||||||
|   liblcms2-2 \ |   liblcms2-2 \ | ||||||
|   libtiff5 \ |   libtiff5 \ | ||||||
|   libxslt1.1 \ |  | ||||||
|   libfreetype6 \ |   libfreetype6 \ | ||||||
|   libwebp6 \ |   libwebp6 \ | ||||||
|   libopenjp2-7 \ |   libopenjp2-7 \ | ||||||
|   libimagequant0 \ |   libimagequant0 \ | ||||||
|   libraqm0 \ |   libraqm0 \ | ||||||
|   libgnutls30 \ |  | ||||||
|   libjpeg62-turbo \ |   libjpeg62-turbo \ | ||||||
|   python3 \ |   # PostgreSQL | ||||||
|   python3-pip \ |   libpq5 \ | ||||||
|   python3-setuptools \ |  | ||||||
|   postgresql-client \ |   postgresql-client \ | ||||||
|  |   # MySQL / MariaDB | ||||||
|   mariadb-client \ |   mariadb-client \ | ||||||
|   # For Numpy |   # For Numpy | ||||||
|   libatlas3-base \ |   libatlas3-base \ | ||||||
| @ -110,17 +113,23 @@ ARG RUNTIME_PACKAGES="\ | |||||||
|   tesseract-ocr-fra \ |   tesseract-ocr-fra \ | ||||||
|   tesseract-ocr-ita \ |   tesseract-ocr-ita \ | ||||||
|   tesseract-ocr-spa \ |   tesseract-ocr-spa \ | ||||||
|   # Suggested for OCRmyPDF |  | ||||||
|   pngquant \ |  | ||||||
|   # Suggested for pikepdf |  | ||||||
|   jbig2dec \ |  | ||||||
|   tzdata \ |  | ||||||
|   unpaper \ |   unpaper \ | ||||||
|  |   pngquant \ | ||||||
|  |   # pikepdf / qpdf | ||||||
|  |   jbig2dec \ | ||||||
|  |   libxml2 \ | ||||||
|  |   libxslt1.1 \ | ||||||
|  |   libgnutls30 \ | ||||||
|   # Mime type detection |   # Mime type detection | ||||||
|  |   file \ | ||||||
|  |   libmagic1 \ | ||||||
|  |   media-types \ | ||||||
|   zlib1g \ |   zlib1g \ | ||||||
|   # Barcode splitter |   # Barcode splitter | ||||||
|   libzbar0 \ |   libzbar0 \ | ||||||
|   poppler-utils" |   poppler-utils \ | ||||||
|  |   # RapidFuzz on armv7 | ||||||
|  |   libatomic1" | ||||||
| 
 | 
 | ||||||
| # Install basic runtime packages. | # Install basic runtime packages. | ||||||
| # These change very infrequently | # These change very infrequently | ||||||
|  | |||||||
							
								
								
									
										7
									
								
								Pipfile
									
									
									
									
									
								
							
							
						
						| @ -60,6 +60,9 @@ setproctitle = "*" | |||||||
| nltk = "*" | nltk = "*" | ||||||
| pdf2image = "*" | pdf2image = "*" | ||||||
| flower = "*" | flower = "*" | ||||||
|  | bleach = "*" | ||||||
|  | # https://www.piwheels.org/project/cryptography/ last built version | ||||||
|  | cryptography = "==38.0.1" | ||||||
| 
 | 
 | ||||||
| [dev-packages] | [dev-packages] | ||||||
| coveralls = "*" | coveralls = "*" | ||||||
| @ -71,10 +74,10 @@ pytest-django = "*" | |||||||
| pytest-env = "*" | pytest-env = "*" | ||||||
| pytest-sugar = "*" | pytest-sugar = "*" | ||||||
| pytest-xdist = "*" | pytest-xdist = "*" | ||||||
| sphinx = "~=5.3" |  | ||||||
| sphinx_rtd_theme = "*" |  | ||||||
| tox = "*" | tox = "*" | ||||||
| black = "*" | black = "*" | ||||||
| pre-commit = "*" | pre-commit = "*" | ||||||
| sphinx-autobuild = "*" | sphinx-autobuild = "*" | ||||||
| myst-parser = "*" | myst-parser = "*" | ||||||
|  | imagehash = "*" | ||||||
|  | mkdocs-material = "*" | ||||||
|  | |||||||
							
								
								
									
										299
									
								
								Pipfile.lock
									
									
									
										generated
									
									
									
								
							
							
						
						| @ -1,7 +1,7 @@ | |||||||
| { | { | ||||||
|     "_meta": { |     "_meta": { | ||||||
|         "hash": { |         "hash": { | ||||||
|             "sha256": "9fefc737155e789ced61b41750b4273c7780ac7801c50cf36dc5925be3b85783" |             "sha256": "cbfe9920231de6e7f993962efb3cc371abdb6b08975232d4cf64d1bad1b53d7a" | ||||||
|         }, |         }, | ||||||
|         "pipfile-spec": 6, |         "pipfile-spec": 6, | ||||||
|         "requires": {}, |         "requires": {}, | ||||||
| @ -99,6 +99,7 @@ | |||||||
|                 "sha256:f04e857b59d9d1ccc39ce2da1021d196e47234873820cbeaad210724b1ee28ac", |                 "sha256:f04e857b59d9d1ccc39ce2da1021d196e47234873820cbeaad210724b1ee28ac", | ||||||
|                 "sha256:fadbfe37f74051d024037f223b8e001611eac868b5c5b06144ef4d8b799862f2" |                 "sha256:fadbfe37f74051d024037f223b8e001611eac868b5c5b06144ef4d8b799862f2" | ||||||
|             ], |             ], | ||||||
|  |             "index": "pypi", | ||||||
|             "markers": "python_version < '3.9'", |             "markers": "python_version < '3.9'", | ||||||
|             "version": "==0.2.1" |             "version": "==0.2.1" | ||||||
|         }, |         }, | ||||||
| @ -109,6 +110,14 @@ | |||||||
|             ], |             ], | ||||||
|             "version": "==3.6.4.0" |             "version": "==3.6.4.0" | ||||||
|         }, |         }, | ||||||
|  |         "bleach": { | ||||||
|  |             "hashes": [ | ||||||
|  |                 "sha256:085f7f33c15bd408dd9b17a4ad77c577db66d76203e5984b1bd59baeee948b2a", | ||||||
|  |                 "sha256:0d03255c47eb9bd2f26aa9bb7f2107732e7e8fe195ca2f64709fcf3b0a4a085c" | ||||||
|  |             ], | ||||||
|  |             "index": "pypi", | ||||||
|  |             "version": "==5.0.1" | ||||||
|  |         }, | ||||||
|         "celery": { |         "celery": { | ||||||
|             "extras": [ |             "extras": [ | ||||||
|                 "redis" |                 "redis" | ||||||
| @ -1766,6 +1775,13 @@ | |||||||
|             ], |             ], | ||||||
|             "version": "==0.2.5" |             "version": "==0.2.5" | ||||||
|         }, |         }, | ||||||
|  |         "webencodings": { | ||||||
|  |             "hashes": [ | ||||||
|  |                 "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", | ||||||
|  |                 "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923" | ||||||
|  |             ], | ||||||
|  |             "version": "==0.5.1" | ||||||
|  |         }, | ||||||
|         "websockets": { |         "websockets": { | ||||||
|             "hashes": [ |             "hashes": [ | ||||||
|                 "sha256:00213676a2e46b6ebf6045bc11d0f529d9120baa6f58d122b4021ad92adabd41", |                 "sha256:00213676a2e46b6ebf6045bc11d0f529d9120baa6f58d122b4021ad92adabd41", | ||||||
| @ -2074,6 +2090,7 @@ | |||||||
|             "version": "==0.4.6" |             "version": "==0.4.6" | ||||||
|         }, |         }, | ||||||
|         "coverage": { |         "coverage": { | ||||||
|  |             "extras": [], | ||||||
|             "hashes": [ |             "hashes": [ | ||||||
|                 "sha256:027018943386e7b942fa832372ebc120155fd970837489896099f5cfa2890f79", |                 "sha256:027018943386e7b942fa832372ebc120155fd970837489896099f5cfa2890f79", | ||||||
|                 "sha256:11b990d520ea75e7ee8dcab5bc908072aaada194a794db9f6d7d5cfd19661e5a", |                 "sha256:11b990d520ea75e7ee8dcab5bc908072aaada194a794db9f6d7d5cfd19661e5a", | ||||||
| @ -2198,6 +2215,13 @@ | |||||||
|             "index": "pypi", |             "index": "pypi", | ||||||
|             "version": "==3.8.0" |             "version": "==3.8.0" | ||||||
|         }, |         }, | ||||||
|  |         "ghp-import": { | ||||||
|  |             "hashes": [ | ||||||
|  |                 "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619", | ||||||
|  |                 "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343" | ||||||
|  |             ], | ||||||
|  |             "version": "==2.1.0" | ||||||
|  |         }, | ||||||
|         "identify": { |         "identify": { | ||||||
|             "hashes": [ |             "hashes": [ | ||||||
|                 "sha256:48b7925fe122720088aeb7a6c34f17b27e706b72c61070f27fe3789094233440", |                 "sha256:48b7925fe122720088aeb7a6c34f17b27e706b72c61070f27fe3789094233440", | ||||||
| @ -2214,6 +2238,14 @@ | |||||||
|             "markers": "python_version >= '3.5'", |             "markers": "python_version >= '3.5'", | ||||||
|             "version": "==3.4" |             "version": "==3.4" | ||||||
|         }, |         }, | ||||||
|  |         "imagehash": { | ||||||
|  |             "hashes": [ | ||||||
|  |                 "sha256:5ad9a5cde14fe255745a8245677293ac0d67f09c330986a351f34b614ba62fb5", | ||||||
|  |                 "sha256:7038d1b7f9e0585beb3dd8c0a956f02b95a346c0b5f24a9e8cc03ebadaf0aa70" | ||||||
|  |             ], | ||||||
|  |             "index": "pypi", | ||||||
|  |             "version": "==4.3.1" | ||||||
|  |         }, | ||||||
|         "imagesize": { |         "imagesize": { | ||||||
|             "hashes": [ |             "hashes": [ | ||||||
|                 "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b", |                 "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b", | ||||||
| @ -2222,6 +2254,14 @@ | |||||||
|             "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", |             "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", | ||||||
|             "version": "==1.4.1" |             "version": "==1.4.1" | ||||||
|         }, |         }, | ||||||
|  |         "importlib-metadata": { | ||||||
|  |             "hashes": [ | ||||||
|  |                 "sha256:d5059f9f1e8e41f80e9c56c2ee58811450c31984dfa625329ffd7c0dad88a73b", | ||||||
|  |                 "sha256:d84d17e21670ec07990e1044a99efe8d615d860fd176fc29ef5c306068fda313" | ||||||
|  |             ], | ||||||
|  |             "markers": "python_version < '3.10'", | ||||||
|  |             "version": "==5.1.0" | ||||||
|  |         }, | ||||||
|         "iniconfig": { |         "iniconfig": { | ||||||
|             "hashes": [ |             "hashes": [ | ||||||
|                 "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3", |                 "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3", | ||||||
| @ -2243,6 +2283,14 @@ | |||||||
|             ], |             ], | ||||||
|             "version": "==2.6.3" |             "version": "==2.6.3" | ||||||
|         }, |         }, | ||||||
|  |         "markdown": { | ||||||
|  |             "hashes": [ | ||||||
|  |                 "sha256:cbb516f16218e643d8e0a95b309f77eb118cb138d39a4f27851e6a63581db874", | ||||||
|  |                 "sha256:f5da449a6e1c989a4cea2631aa8ee67caa5a2ef855d551c88f9e309f4634c621" | ||||||
|  |             ], | ||||||
|  |             "markers": "python_version >= '3.6'", | ||||||
|  |             "version": "==3.3.7" | ||||||
|  |         }, | ||||||
|         "markdown-it-py": { |         "markdown-it-py": { | ||||||
|             "hashes": [ |             "hashes": [ | ||||||
|                 "sha256:93de681e5c021a432c63147656fe21790bc01231e0cd2da73626f1aa3ac0fe27", |                 "sha256:93de681e5c021a432c63147656fe21790bc01231e0cd2da73626f1aa3ac0fe27", | ||||||
| @ -2313,6 +2361,38 @@ | |||||||
|             "markers": "python_version >= '3.7'", |             "markers": "python_version >= '3.7'", | ||||||
|             "version": "==0.1.2" |             "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": { |         "mypy-extensions": { | ||||||
|             "hashes": [ |             "hashes": [ | ||||||
|                 "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d", |                 "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d", | ||||||
| @ -2336,6 +2416,40 @@ | |||||||
|             "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", |             "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", | ||||||
|             "version": "==1.7.0" |             "version": "==1.7.0" | ||||||
|         }, |         }, | ||||||
|  |         "numpy": { | ||||||
|  |             "hashes": [ | ||||||
|  |                 "sha256:0fe563fc8ed9dc4474cbf70742673fc4391d70f4363f917599a7fa99f042d5a8", | ||||||
|  |                 "sha256:12ac457b63ec8ded85d85c1e17d85efd3c2b0967ca39560b307a35a6703a4735", | ||||||
|  |                 "sha256:2341f4ab6dba0834b685cce16dad5f9b6606ea8a00e6da154f5dbded70fdc4dd", | ||||||
|  |                 "sha256:296d17aed51161dbad3c67ed6d164e51fcd18dbcd5dd4f9d0a9c6055dce30810", | ||||||
|  |                 "sha256:488a66cb667359534bc70028d653ba1cf307bae88eab5929cd707c761ff037db", | ||||||
|  |                 "sha256:4d52914c88b4930dafb6c48ba5115a96cbab40f45740239d9f4159c4ba779962", | ||||||
|  |                 "sha256:5e13030f8793e9ee42f9c7d5777465a560eb78fa7e11b1c053427f2ccab90c79", | ||||||
|  |                 "sha256:61be02e3bf810b60ab74e81d6d0d36246dbfb644a462458bb53b595791251911", | ||||||
|  |                 "sha256:7607b598217745cc40f751da38ffd03512d33ec06f3523fb0b5f82e09f6f676d", | ||||||
|  |                 "sha256:7a70a7d3ce4c0e9284e92285cba91a4a3f5214d87ee0e95928f3614a256a1488", | ||||||
|  |                 "sha256:7ab46e4e7ec63c8a5e6dbf5c1b9e1c92ba23a7ebecc86c336cb7bf3bd2fb10e5", | ||||||
|  |                 "sha256:8981d9b5619569899666170c7c9748920f4a5005bf79c72c07d08c8a035757b0", | ||||||
|  |                 "sha256:8c053d7557a8f022ec823196d242464b6955a7e7e5015b719e76003f63f82d0f", | ||||||
|  |                 "sha256:926db372bc4ac1edf81cfb6c59e2a881606b409ddc0d0920b988174b2e2a767f", | ||||||
|  |                 "sha256:95d79ada05005f6f4f337d3bb9de8a7774f259341c70bc88047a1f7b96a4bcb2", | ||||||
|  |                 "sha256:95de7dc7dc47a312f6feddd3da2500826defdccbc41608d0031276a24181a2c0", | ||||||
|  |                 "sha256:a0882323e0ca4245eb0a3d0a74f88ce581cc33aedcfa396e415e5bba7bf05f68", | ||||||
|  |                 "sha256:a8365b942f9c1a7d0f0dc974747d99dd0a0cdfc5949a33119caf05cb314682d3", | ||||||
|  |                 "sha256:a8aae2fb3180940011b4862b2dd3756616841c53db9734b27bb93813cd79fce6", | ||||||
|  |                 "sha256:c237129f0e732885c9a6076a537e974160482eab8f10db6292e92154d4c67d71", | ||||||
|  |                 "sha256:c67b833dbccefe97cdd3f52798d430b9d3430396af7cdb2a0c32954c3ef73894", | ||||||
|  |                 "sha256:ce03305dd694c4873b9429274fd41fc7eb4e0e4dea07e0af97a933b079a5814f", | ||||||
|  |                 "sha256:d331afac87c92373826af83d2b2b435f57b17a5c74e6268b79355b970626e329", | ||||||
|  |                 "sha256:dada341ebb79619fe00a291185bba370c9803b1e1d7051610e01ed809ef3a4ba", | ||||||
|  |                 "sha256:ed2cc92af0efad20198638c69bb0fc2870a58dabfba6eb722c933b48556c686c", | ||||||
|  |                 "sha256:f260da502d7441a45695199b4e7fd8ca87db659ba1c78f2bbf31f934fe76ae0e", | ||||||
|  |                 "sha256:f2f390aa4da44454db40a1f0201401f9036e8d578a25f01a6e237cea238337ef", | ||||||
|  |                 "sha256:f76025acc8e2114bb664294a07ede0727aa75d63a06d2fae96bf29a81747e4a7" | ||||||
|  |             ], | ||||||
|  |             "index": "pypi", | ||||||
|  |             "version": "==1.23.4" | ||||||
|  |         }, | ||||||
|         "packaging": { |         "packaging": { | ||||||
|             "hashes": [ |             "hashes": [ | ||||||
|                 "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb", |                 "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb", | ||||||
| @ -2352,6 +2466,73 @@ | |||||||
|             "markers": "python_version >= '3.7'", |             "markers": "python_version >= '3.7'", | ||||||
|             "version": "==0.10.1" |             "version": "==0.10.1" | ||||||
|         }, |         }, | ||||||
|  |         "pillow": { | ||||||
|  |             "hashes": [ | ||||||
|  |                 "sha256:03150abd92771742d4a8cd6f2fa6246d847dcd2e332a18d0c15cc75bf6703040", | ||||||
|  |                 "sha256:073adb2ae23431d3b9bcbcff3fe698b62ed47211d0716b067385538a1b0f28b8", | ||||||
|  |                 "sha256:0b07fffc13f474264c336298d1b4ce01d9c5a011415b79d4ee5527bb69ae6f65", | ||||||
|  |                 "sha256:0b7257127d646ff8676ec8a15520013a698d1fdc48bc2a79ba4e53df792526f2", | ||||||
|  |                 "sha256:12ce4932caf2ddf3e41d17fc9c02d67126935a44b86df6a206cf0d7161548627", | ||||||
|  |                 "sha256:15c42fb9dea42465dfd902fb0ecf584b8848ceb28b41ee2b58f866411be33f07", | ||||||
|  |                 "sha256:18498994b29e1cf86d505edcb7edbe814d133d2232d256db8c7a8ceb34d18cef", | ||||||
|  |                 "sha256:1c7c8ae3864846fc95f4611c78129301e203aaa2af813b703c55d10cc1628535", | ||||||
|  |                 "sha256:22b012ea2d065fd163ca096f4e37e47cd8b59cf4b0fd47bfca6abb93df70b34c", | ||||||
|  |                 "sha256:276a5ca930c913f714e372b2591a22c4bd3b81a418c0f6635ba832daec1cbcfc", | ||||||
|  |                 "sha256:2e0918e03aa0c72ea56edbb00d4d664294815aa11291a11504a377ea018330d3", | ||||||
|  |                 "sha256:3033fbe1feb1b59394615a1cafaee85e49d01b51d54de0cbf6aa8e64182518a1", | ||||||
|  |                 "sha256:3168434d303babf495d4ba58fc22d6604f6e2afb97adc6a423e917dab828939c", | ||||||
|  |                 "sha256:32a44128c4bdca7f31de5be641187367fe2a450ad83b833ef78910397db491aa", | ||||||
|  |                 "sha256:3dd6caf940756101205dffc5367babf288a30043d35f80936f9bfb37f8355b32", | ||||||
|  |                 "sha256:40e1ce476a7804b0fb74bcfa80b0a2206ea6a882938eaba917f7a0f004b42502", | ||||||
|  |                 "sha256:41e0051336807468be450d52b8edd12ac60bebaa97fe10c8b660f116e50b30e4", | ||||||
|  |                 "sha256:4390e9ce199fc1951fcfa65795f239a8a4944117b5935a9317fb320e7767b40f", | ||||||
|  |                 "sha256:502526a2cbfa431d9fc2a079bdd9061a2397b842bb6bc4239bb176da00993812", | ||||||
|  |                 "sha256:51e0e543a33ed92db9f5ef69a0356e0b1a7a6b6a71b80df99f1d181ae5875636", | ||||||
|  |                 "sha256:57751894f6618fd4308ed8e0c36c333e2f5469744c34729a27532b3db106ee20", | ||||||
|  |                 "sha256:5d77adcd56a42d00cc1be30843d3426aa4e660cab4a61021dc84467123f7a00c", | ||||||
|  |                 "sha256:655a83b0058ba47c7c52e4e2df5ecf484c1b0b0349805896dd350cbc416bdd91", | ||||||
|  |                 "sha256:68943d632f1f9e3dce98908e873b3a090f6cba1cbb1b892a9e8d97c938871fbe", | ||||||
|  |                 "sha256:6c738585d7a9961d8c2821a1eb3dcb978d14e238be3d70f0a706f7fa9316946b", | ||||||
|  |                 "sha256:73bd195e43f3fadecfc50c682f5055ec32ee2c933243cafbfdec69ab1aa87cad", | ||||||
|  |                 "sha256:772a91fc0e03eaf922c63badeca75e91baa80fe2f5f87bdaed4280662aad25c9", | ||||||
|  |                 "sha256:77ec3e7be99629898c9a6d24a09de089fa5356ee408cdffffe62d67bb75fdd72", | ||||||
|  |                 "sha256:7db8b751ad307d7cf238f02101e8e36a128a6cb199326e867d1398067381bff4", | ||||||
|  |                 "sha256:801ec82e4188e935c7f5e22e006d01611d6b41661bba9fe45b60e7ac1a8f84de", | ||||||
|  |                 "sha256:82409ffe29d70fd733ff3c1025a602abb3e67405d41b9403b00b01debc4c9a29", | ||||||
|  |                 "sha256:828989c45c245518065a110434246c44a56a8b2b2f6347d1409c787e6e4651ee", | ||||||
|  |                 "sha256:829f97c8e258593b9daa80638aee3789b7df9da5cf1336035016d76f03b8860c", | ||||||
|  |                 "sha256:871b72c3643e516db4ecf20efe735deb27fe30ca17800e661d769faab45a18d7", | ||||||
|  |                 "sha256:89dca0ce00a2b49024df6325925555d406b14aa3efc2f752dbb5940c52c56b11", | ||||||
|  |                 "sha256:90fb88843d3902fe7c9586d439d1e8c05258f41da473952aa8b328d8b907498c", | ||||||
|  |                 "sha256:97aabc5c50312afa5e0a2b07c17d4ac5e865b250986f8afe2b02d772567a380c", | ||||||
|  |                 "sha256:9aaa107275d8527e9d6e7670b64aabaaa36e5b6bd71a1015ddd21da0d4e06448", | ||||||
|  |                 "sha256:9f47eabcd2ded7698106b05c2c338672d16a6f2a485e74481f524e2a23c2794b", | ||||||
|  |                 "sha256:a0a06a052c5f37b4ed81c613a455a81f9a3a69429b4fd7bb913c3fa98abefc20", | ||||||
|  |                 "sha256:ab388aaa3f6ce52ac1cb8e122c4bd46657c15905904b3120a6248b5b8b0bc228", | ||||||
|  |                 "sha256:ad58d27a5b0262c0c19b47d54c5802db9b34d38bbf886665b626aff83c74bacd", | ||||||
|  |                 "sha256:ae5331c23ce118c53b172fa64a4c037eb83c9165aba3a7ba9ddd3ec9fa64a699", | ||||||
|  |                 "sha256:af0372acb5d3598f36ec0914deed2a63f6bcdb7b606da04dc19a88d31bf0c05b", | ||||||
|  |                 "sha256:afa4107d1b306cdf8953edde0534562607fe8811b6c4d9a486298ad31de733b2", | ||||||
|  |                 "sha256:b03ae6f1a1878233ac620c98f3459f79fd77c7e3c2b20d460284e1fb370557d4", | ||||||
|  |                 "sha256:b0915e734b33a474d76c28e07292f196cdf2a590a0d25bcc06e64e545f2d146c", | ||||||
|  |                 "sha256:b4012d06c846dc2b80651b120e2cdd787b013deb39c09f407727ba90015c684f", | ||||||
|  |                 "sha256:b472b5ea442148d1c3e2209f20f1e0bb0eb556538690fa70b5e1f79fa0ba8dc2", | ||||||
|  |                 "sha256:b59430236b8e58840a0dfb4099a0e8717ffb779c952426a69ae435ca1f57210c", | ||||||
|  |                 "sha256:b90f7616ea170e92820775ed47e136208e04c967271c9ef615b6fbd08d9af0e3", | ||||||
|  |                 "sha256:b9a65733d103311331875c1dca05cb4606997fd33d6acfed695b1232ba1df193", | ||||||
|  |                 "sha256:bac18ab8d2d1e6b4ce25e3424f709aceef668347db8637c2296bcf41acb7cf48", | ||||||
|  |                 "sha256:bca31dd6014cb8b0b2db1e46081b0ca7d936f856da3b39744aef499db5d84d02", | ||||||
|  |                 "sha256:be55f8457cd1eac957af0c3f5ece7bc3f033f89b114ef30f710882717670b2a8", | ||||||
|  |                 "sha256:c7025dce65566eb6e89f56c9509d4f628fddcedb131d9465cacd3d8bac337e7e", | ||||||
|  |                 "sha256:c935a22a557a560108d780f9a0fc426dd7459940dc54faa49d83249c8d3e760f", | ||||||
|  |                 "sha256:dbb8e7f2abee51cef77673be97760abff1674ed32847ce04b4af90f610144c7b", | ||||||
|  |                 "sha256:e6ea6b856a74d560d9326c0f5895ef8050126acfdc7ca08ad703eb0081e82b74", | ||||||
|  |                 "sha256:ebf2029c1f464c59b8bdbe5143c79fa2045a581ac53679733d3a91d400ff9efb", | ||||||
|  |                 "sha256:f1ff2ee69f10f13a9596480335f406dd1f70c3650349e2be67ca3139280cade0" | ||||||
|  |             ], | ||||||
|  |             "index": "pypi", | ||||||
|  |             "version": "==9.3.0" | ||||||
|  |         }, | ||||||
|         "platformdirs": { |         "platformdirs": { | ||||||
|             "hashes": [ |             "hashes": [ | ||||||
|                 "sha256:0cb405749187a194f444c25c82ef7225232f11564721eabffc6ec70df83b11cb", |                 "sha256:0cb405749187a194f444c25c82ef7225232f11564721eabffc6ec70df83b11cb", | ||||||
| @ -2400,6 +2581,14 @@ | |||||||
|             "markers": "python_version >= '3.6'", |             "markers": "python_version >= '3.6'", | ||||||
|             "version": "==2.13.0" |             "version": "==2.13.0" | ||||||
|         }, |         }, | ||||||
|  |         "pymdown-extensions": { | ||||||
|  |             "hashes": [ | ||||||
|  |                 "sha256:0f8fb7b74a37a61cc34e90b2c91865458b713ec774894ffad64353a5fce85cfc", | ||||||
|  |                 "sha256:ac698c15265680db5eb13cd4342abfcde2079ac01e5486028f47a1b41547b859" | ||||||
|  |             ], | ||||||
|  |             "markers": "python_version >= '3.7'", | ||||||
|  |             "version": "==9.9" | ||||||
|  |         }, | ||||||
|         "pyparsing": { |         "pyparsing": { | ||||||
|             "hashes": [ |             "hashes": [ | ||||||
|                 "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb", |                 "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb", | ||||||
| @ -2471,6 +2660,37 @@ | |||||||
|             ], |             ], | ||||||
|             "version": "==2022.6" |             "version": "==2022.6" | ||||||
|         }, |         }, | ||||||
|  |         "pywavelets": { | ||||||
|  |             "hashes": [ | ||||||
|  |                 "sha256:030670a213ee8fefa56f6387b0c8e7d970c7f7ad6850dc048bd7c89364771b9b", | ||||||
|  |                 "sha256:058b46434eac4c04dd89aeef6fa39e4b6496a951d78c500b6641fd5b2cc2f9f4", | ||||||
|  |                 "sha256:231b0e0b1cdc1112f4af3c24eea7bf181c418d37922a67670e9bf6cfa2d544d4", | ||||||
|  |                 "sha256:23bafd60350b2b868076d976bdd92f950b3944f119b4754b1d7ff22b7acbf6c6", | ||||||
|  |                 "sha256:3f19327f2129fb7977bc59b966b4974dfd72879c093e44a7287500a7032695de", | ||||||
|  |                 "sha256:47cac4fa25bed76a45bc781a293c26ac63e8eaae9eb8f9be961758d22b58649c", | ||||||
|  |                 "sha256:578af438a02a86b70f1975b546f68aaaf38f28fb082a61ceb799816049ed18aa", | ||||||
|  |                 "sha256:6437af3ddf083118c26d8f97ab43b0724b956c9f958e9ea788659f6a2834ba93", | ||||||
|  |                 "sha256:64c6bac6204327321db30b775060fbe8e8642316e6bff17f06b9f34936f88875", | ||||||
|  |                 "sha256:67a0d28a08909f21400cb09ff62ba94c064882ffd9e3a6b27880a111211d59bd", | ||||||
|  |                 "sha256:71ab30f51ee4470741bb55fc6b197b4a2b612232e30f6ac069106f0156342356", | ||||||
|  |                 "sha256:7231461d7a8eb3bdc7aa2d97d9f67ea5a9f8902522818e7e2ead9c2b3408eeb1", | ||||||
|  |                 "sha256:754fa5085768227c4f4a26c1e0c78bc509a266d9ebd0eb69a278be7e3ece943c", | ||||||
|  |                 "sha256:7ab8d9db0fe549ab2ee0bea61f614e658dd2df419d5b75fba47baa761e95f8f2", | ||||||
|  |                 "sha256:875d4d620eee655346e3589a16a73790cf9f8917abba062234439b594e706784", | ||||||
|  |                 "sha256:88aa5449e109d8f5e7f0adef85f7f73b1ab086102865be64421a3a3d02d277f4", | ||||||
|  |                 "sha256:91d3d393cffa634f0e550d88c0e3f217c96cfb9e32781f2960876f1808d9b45b", | ||||||
|  |                 "sha256:9cb5ca8d11d3f98e89e65796a2125be98424d22e5ada360a0dbabff659fca0fc", | ||||||
|  |                 "sha256:ab7da0a17822cd2f6545626946d3b82d1a8e106afc4b50e3387719ba01c7b966", | ||||||
|  |                 "sha256:ad987748f60418d5f4138db89d82ba0cb49b086e0cbb8fd5c3ed4a814cfb705e", | ||||||
|  |                 "sha256:d0e56cd7a53aed3cceca91a04d62feb3a0aca6725b1912d29546c26f6ea90426", | ||||||
|  |                 "sha256:d854411eb5ee9cb4bc5d0e66e3634aeb8f594210f6a1bed96dbed57ec70f181c", | ||||||
|  |                 "sha256:da7b9c006171be1f9ddb12cc6e0d3d703b95f7f43cb5e2c6f5f15d3233fcf202", | ||||||
|  |                 "sha256:daf0aa79842b571308d7c31a9c43bc99a30b6328e6aea3f50388cd8f69ba7dbc", | ||||||
|  |                 "sha256:de7cd61a88a982edfec01ea755b0740e94766e00a1ceceeafef3ed4c85c605cd" | ||||||
|  |             ], | ||||||
|  |             "markers": "python_version >= '3.8'", | ||||||
|  |             "version": "==1.4.1" | ||||||
|  |         }, | ||||||
|         "pyyaml": { |         "pyyaml": { | ||||||
|             "hashes": [ |             "hashes": [ | ||||||
|                 "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf", |                 "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf", | ||||||
| @ -2516,6 +2736,14 @@ | |||||||
|             ], |             ], | ||||||
|             "version": "==6.0" |             "version": "==6.0" | ||||||
|         }, |         }, | ||||||
|  |         "pyyaml-env-tag": { | ||||||
|  |             "hashes": [ | ||||||
|  |                 "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb", | ||||||
|  |                 "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069" | ||||||
|  |             ], | ||||||
|  |             "markers": "python_version >= '3.6'", | ||||||
|  |             "version": "==0.1" | ||||||
|  |         }, | ||||||
|         "requests": { |         "requests": { | ||||||
|             "hashes": [ |             "hashes": [ | ||||||
|                 "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983", |                 "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983", | ||||||
| @ -2524,6 +2752,35 @@ | |||||||
|             "markers": "python_version >= '3.7' and python_version < '4'", |             "markers": "python_version >= '3.7' and python_version < '4'", | ||||||
|             "version": "==2.28.1" |             "version": "==2.28.1" | ||||||
|         }, |         }, | ||||||
|  |         "scipy": { | ||||||
|  |             "hashes": [ | ||||||
|  |                 "sha256:02b567e722d62bddd4ac253dafb01ce7ed8742cf8031aea030a41414b86c1125", | ||||||
|  |                 "sha256:1166514aa3bbf04cb5941027c6e294a000bba0cf00f5cdac6c77f2dad479b434", | ||||||
|  |                 "sha256:1da52b45ce1a24a4a22db6c157c38b39885a990a566748fc904ec9f03ed8c6ba", | ||||||
|  |                 "sha256:23b22fbeef3807966ea42d8163322366dd89da9bebdc075da7034cee3a1441ca", | ||||||
|  |                 "sha256:28d2cab0c6ac5aa131cc5071a3a1d8e1366dad82288d9ec2ca44df78fb50e649", | ||||||
|  |                 "sha256:2ef0fbc8bcf102c1998c1f16f15befe7cffba90895d6e84861cd6c6a33fb54f6", | ||||||
|  |                 "sha256:3b69b90c9419884efeffaac2c38376d6ef566e6e730a231e15722b0ab58f0328", | ||||||
|  |                 "sha256:4b93ec6f4c3c4d041b26b5f179a6aab8f5045423117ae7a45ba9710301d7e462", | ||||||
|  |                 "sha256:4e53a55f6a4f22de01ffe1d2f016e30adedb67a699a310cdcac312806807ca81", | ||||||
|  |                 "sha256:6311e3ae9cc75f77c33076cb2794fb0606f14c8f1b1c9ff8ce6005ba2c283621", | ||||||
|  |                 "sha256:65b77f20202599c51eb2771d11a6b899b97989159b7975e9b5259594f1d35ef4", | ||||||
|  |                 "sha256:6cc6b33139eb63f30725d5f7fa175763dc2df6a8f38ddf8df971f7c345b652dc", | ||||||
|  |                 "sha256:70de2f11bf64ca9921fda018864c78af7147025e467ce9f4a11bc877266900a6", | ||||||
|  |                 "sha256:70ebc84134cf0c504ce6a5f12d6db92cb2a8a53a49437a6bb4edca0bc101f11c", | ||||||
|  |                 "sha256:83606129247e7610b58d0e1e93d2c5133959e9cf93555d3c27e536892f1ba1f2", | ||||||
|  |                 "sha256:93d07494a8900d55492401917a119948ed330b8c3f1d700e0b904a578f10ead4", | ||||||
|  |                 "sha256:9c4e3ae8a716c8b3151e16c05edb1daf4cb4d866caa385e861556aff41300c14", | ||||||
|  |                 "sha256:9dd4012ac599a1e7eb63c114d1eee1bcfc6dc75a29b589ff0ad0bb3d9412034f", | ||||||
|  |                 "sha256:9e3fb1b0e896f14a85aa9a28d5f755daaeeb54c897b746df7a55ccb02b340f33", | ||||||
|  |                 "sha256:a0aa8220b89b2e3748a2836fbfa116194378910f1a6e78e4675a095bcd2c762d", | ||||||
|  |                 "sha256:d3b3c8924252caaffc54d4a99f1360aeec001e61267595561089f8b5900821bb", | ||||||
|  |                 "sha256:e013aed00ed776d790be4cb32826adb72799c61e318676172495383ba4570aa4", | ||||||
|  |                 "sha256:f3e7a8867f307e3359cc0ed2c63b61a1e33a19080f92fe377bc7d49f646f2ec1" | ||||||
|  |             ], | ||||||
|  |             "index": "pypi", | ||||||
|  |             "version": "==1.8.1" | ||||||
|  |         }, | ||||||
|         "setuptools": { |         "setuptools": { | ||||||
|             "hashes": [ |             "hashes": [ | ||||||
|                 "sha256:d0b9a8433464d5800cbe05094acf5c6d52a91bfac9b52bcfc4d41382be5d5d31", |                 "sha256:d0b9a8433464d5800cbe05094acf5c6d52a91bfac9b52bcfc4d41382be5d5d31", | ||||||
| @ -2552,7 +2809,6 @@ | |||||||
|                 "sha256:060ca5c9f7ba57a08a1219e547b269fadf125ae25b06b9fa7f66768efb652d6d", |                 "sha256:060ca5c9f7ba57a08a1219e547b269fadf125ae25b06b9fa7f66768efb652d6d", | ||||||
|                 "sha256:51026de0a9ff9fc13c05d74913ad66047e104f56a129ff73e174eb5c3ee794b5" |                 "sha256:51026de0a9ff9fc13c05d74913ad66047e104f56a129ff73e174eb5c3ee794b5" | ||||||
|             ], |             ], | ||||||
|             "index": "pypi", |  | ||||||
|             "version": "==5.3.0" |             "version": "==5.3.0" | ||||||
|         }, |         }, | ||||||
|         "sphinx-autobuild": { |         "sphinx-autobuild": { | ||||||
| @ -2691,6 +2947,45 @@ | |||||||
|             ], |             ], | ||||||
|             "markers": "python_version >= '3.6'", |             "markers": "python_version >= '3.6'", | ||||||
|             "version": "==20.16.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" | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										22
									
								
								README.md
									
									
									
									
									
								
							
							
						
						| @ -1,8 +1,9 @@ | |||||||
| [](https://github.com/paperless-ngx/paperless-ngx/actions) | [](https://github.com/paperless-ngx/paperless-ngx/actions) | ||||||
| [](https://crowdin.com/project/paperless-ngx) | [](https://crowdin.com/project/paperless-ngx) | ||||||
| [](https://paperless-ngx.readthedocs.io/en/latest/?badge=latest) | [](https://docs.paperless-ngx.com) | ||||||
| [](https://coveralls.io/github/paperless-ngx/paperless-ngx?branch=master) | [](https://coveralls.io/github/paperless-ngx/paperless-ngx?branch=master) | ||||||
| [](https://matrix.to/#/#paperless:adnidor.de) | [](https://matrix.to/#/%23paperlessngx%3Amatrix.org) | ||||||
|  | [](https://demo.paperless-ngx.com) | ||||||
| 
 | 
 | ||||||
| <p align="center"> | <p align="center"> | ||||||
| <img src="https://github.com/paperless-ngx/paperless-ngx/raw/main/resources/logo/web/png/Black%20logo%20-%20no%20background.png#gh-light-mode-only" width="50%" /> | <img src="https://github.com/paperless-ngx/paperless-ngx/raw/main/resources/logo/web/png/Black%20logo%20-%20no%20background.png#gh-light-mode-only" width="50%" /> | ||||||
| @ -32,13 +33,13 @@ A demo is available at [demo.paperless-ngx.com](https://demo.paperless-ngx.com) | |||||||
| 
 | 
 | ||||||
| # Features | # Features | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  |  | ||||||
| 
 | 
 | ||||||
| - Organize and index your scanned documents with tags, correspondents, types, and more. | - Organize and index your scanned documents with tags, correspondents, types, and more. | ||||||
| - Performs OCR on your documents, adds selectable text to image only documents and adds tags, correspondents and document types to your documents. | - Performs OCR on your documents, adds selectable text to image only documents and adds tags, correspondents and document types to your documents. | ||||||
| - Supports PDF documents, images, plain text files, and Office documents (Word, Excel, Powerpoint, and LibreOffice equivalents). | - Supports PDF documents, images, plain text files, and Office documents (Word, Excel, Powerpoint, and LibreOffice equivalents). | ||||||
|   - Office document support is optional and provided by Apache Tika (see [configuration](https://paperless-ngx.readthedocs.io/en/latest/configuration.html#tika-settings)) |   - Office document support is optional and provided by Apache Tika (see [configuration](https://docs.paperless-ngx.com/configuration/#tika)) | ||||||
| - Paperless stores your documents plain on disk. Filenames and folders are managed by paperless and their format can be configured freely. | - Paperless stores your documents plain on disk. Filenames and folders are managed by paperless and their format can be configured freely. | ||||||
| - Single page application front end. | - Single page application front end. | ||||||
|   - Includes a dashboard that shows basic statistics and has document upload. |   - Includes a dashboard that shows basic statistics and has document upload. | ||||||
| @ -56,7 +57,7 @@ A demo is available at [demo.paperless-ngx.com](https://demo.paperless-ngx.com) | |||||||
|   - Paperless-ngx learns from your documents and will be able to automatically assign tags, correspondents and types to documents once you've stored a few documents in paperless. |   - Paperless-ngx learns from your documents and will be able to automatically assign tags, correspondents and types to documents once you've stored a few documents in paperless. | ||||||
| - Optimized for multi core systems: Paperless-ngx consumes multiple documents in parallel. | - Optimized for multi core systems: Paperless-ngx consumes multiple documents in parallel. | ||||||
| - The integrated sanity checker makes sure that your document archive is in good health. | - The integrated sanity checker makes sure that your document archive is in good health. | ||||||
| - [More screenshots are available in the documentation](https://paperless-ngx.readthedocs.io/en/latest/screenshots.html). | - [More screenshots are available in the documentation](https://docs.paperless-ngx.com/#screenshots). | ||||||
| 
 | 
 | ||||||
| # Getting started | # Getting started | ||||||
| 
 | 
 | ||||||
| @ -68,19 +69,19 @@ If you'd like to jump right in, you can configure a docker-compose environment w | |||||||
| bash -c "$(curl -L https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/install-paperless-ngx.sh)" | bash -c "$(curl -L https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/install-paperless-ngx.sh)" | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| Alternatively, you can install the dependencies and setup apache and a database server yourself. The [documentation](https://paperless-ngx.readthedocs.io/en/latest/setup.html#installation) has a step by step guide on how to do it. | Alternatively, you can install the dependencies and setup apache and a database server yourself. The [documentation](https://docs.paperless-ngx.com/setup/#installation) has a step by step guide on how to do it. | ||||||
| 
 | 
 | ||||||
| Migrating from Paperless-ng is easy, just drop in the new docker image! See the [documentation on migrating](https://paperless-ngx.readthedocs.io/en/latest/setup.html#migrating-from-paperless-ng) for more details. | Migrating from Paperless-ng is easy, just drop in the new docker image! See the [documentation on migrating](https://docs.paperless-ngx.com/setup/#migrating-to-paperless-ngx) for more details. | ||||||
| 
 | 
 | ||||||
| <!-- omit in toc --> | <!-- omit in toc --> | ||||||
| 
 | 
 | ||||||
| ### Documentation | ### Documentation | ||||||
| 
 | 
 | ||||||
| The documentation for Paperless-ngx is available on [ReadTheDocs](https://paperless-ngx.readthedocs.io/). | The documentation for Paperless-ngx is available at [https://docs.paperless-ngx.com](https://docs.paperless-ngx.com/). | ||||||
| 
 | 
 | ||||||
| # Contributing | # Contributing | ||||||
| 
 | 
 | ||||||
| If you feel like contributing to the project, please do! Bug fixes, enhancements, visual fixes etc. are always welcome. If you want to implement something big: Please start a discussion about that! The [documentation](https://paperless-ngx.readthedocs.io/en/latest/extending.html) has some basic information on how to get started. | If you feel like contributing to the project, please do! Bug fixes, enhancements, visual fixes etc. are always welcome. If you want to implement something big: Please start a discussion about that! The [documentation](https://docs.paperless-ngx.com/development/) has some basic information on how to get started. | ||||||
| 
 | 
 | ||||||
| ## Community Support | ## Community Support | ||||||
| 
 | 
 | ||||||
| @ -105,6 +106,7 @@ Paperless has been around a while now, and people are starting to build stuff on | |||||||
| - [Paperless App](https://github.com/bauerj/paperless_app): An Android/iOS app for Paperless-ngx. Also works with the original Paperless and Paperless-ng. | - [Paperless App](https://github.com/bauerj/paperless_app): An Android/iOS app for Paperless-ngx. Also works with the original Paperless and Paperless-ng. | ||||||
| - [Paperless Share](https://github.com/qcasey/paperless_share). Share any files from your Android application with paperless. Very simple, but works with all of the mobile scanning apps out there that allow you to share scanned documents. | - [Paperless Share](https://github.com/qcasey/paperless_share). Share any files from your Android application with paperless. Very simple, but works with all of the mobile scanning apps out there that allow you to share scanned documents. | ||||||
| - [Scan to Paperless](https://github.com/sbrunner/scan-to-paperless): Scan and prepare (crop, deskew, OCR, ...) your documents for Paperless. | - [Scan to Paperless](https://github.com/sbrunner/scan-to-paperless): Scan and prepare (crop, deskew, OCR, ...) your documents for Paperless. | ||||||
|  | - [Paperless Mobile](https://github.com/astubenbord/paperless-mobile): A modern, feature rich mobile application for Paperless. | ||||||
| 
 | 
 | ||||||
| These projects also exist, but their status and compatibility with paperless-ngx is unknown. | These projects also exist, but their status and compatibility with paperless-ngx is unknown. | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										26
									
								
								charts/paperless-ngx/.helmignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,26 @@ | |||||||
|  | # Patterns to ignore when building packages. | ||||||
|  | # This supports shell glob matching, relative path matching, and | ||||||
|  | # negation (prefixed with !). Only one pattern per line. | ||||||
|  | .DS_Store | ||||||
|  | # Common VCS dirs | ||||||
|  | .git/ | ||||||
|  | .gitignore | ||||||
|  | .bzr/ | ||||||
|  | .bzrignore | ||||||
|  | .hg/ | ||||||
|  | .hgignore | ||||||
|  | .svn/ | ||||||
|  | # Common backup files | ||||||
|  | *.swp | ||||||
|  | *.bak | ||||||
|  | *.tmp | ||||||
|  | *~ | ||||||
|  | # Various IDEs | ||||||
|  | .project | ||||||
|  | .idea/ | ||||||
|  | *.tmproj | ||||||
|  | .vscode/ | ||||||
|  | # OWNERS file for Kubernetes | ||||||
|  | OWNERS | ||||||
|  | # helm-docs templates | ||||||
|  | *.gotmpl | ||||||
							
								
								
									
										35
									
								
								charts/paperless-ngx/Chart.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,35 @@ | |||||||
|  | --- | ||||||
|  | apiVersion: v2 | ||||||
|  | appVersion: "1.9.2" | ||||||
|  | description: Paperless-ngx - Index and archive all of your scanned paper documents | ||||||
|  | name: paperless | ||||||
|  | version: 10.0.0 | ||||||
|  | kubeVersion: ">=1.16.0-0" | ||||||
|  | keywords: | ||||||
|  |   - paperless | ||||||
|  |   - paperless-ngx | ||||||
|  |   - dms | ||||||
|  |   - document | ||||||
|  | home: https://github.com/paperless-ngx/paperless-ngx/tree/main/charts/paperless-ngx | ||||||
|  | icon: https://github.com/paperless-ngx/paperless-ngx/raw/main/resources/logo/web/svg/square.svg | ||||||
|  | sources: | ||||||
|  |   - https://github.com/paperless-ngx/paperless-ngx | ||||||
|  | maintainers: | ||||||
|  |   - name: Paperless-ngx maintainers | ||||||
|  | dependencies: | ||||||
|  |   - name: common | ||||||
|  |     repository: https://library-charts.k8s-at-home.com | ||||||
|  |     version: 4.5.2 | ||||||
|  |   - name: postgresql | ||||||
|  |     version: 11.6.12 | ||||||
|  |     repository: https://charts.bitnami.com/bitnami | ||||||
|  |     condition: postgresql.enabled | ||||||
|  |   - name: redis | ||||||
|  |     version: 16.13.1 | ||||||
|  |     repository: https://charts.bitnami.com/bitnami | ||||||
|  |     condition: redis.enabled | ||||||
|  | deprecated: false | ||||||
|  | annotations: | ||||||
|  |   artifacthub.io/changes: | | ||||||
|  |     - kind: changed | ||||||
|  |       description: Moved to Paperless-ngx ownership | ||||||
							
								
								
									
										201
									
								
								charts/paperless-ngx/LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,201 @@ | |||||||
|  |                                  Apache License | ||||||
|  |                            Version 2.0, January 2004 | ||||||
|  |                         http://www.apache.org/licenses/ | ||||||
|  | 
 | ||||||
|  |    TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||||||
|  | 
 | ||||||
|  |    1. Definitions. | ||||||
|  | 
 | ||||||
|  |       "License" shall mean the terms and conditions for use, reproduction, | ||||||
|  |       and distribution as defined by Sections 1 through 9 of this document. | ||||||
|  | 
 | ||||||
|  |       "Licensor" shall mean the copyright owner or entity authorized by | ||||||
|  |       the copyright owner that is granting the License. | ||||||
|  | 
 | ||||||
|  |       "Legal Entity" shall mean the union of the acting entity and all | ||||||
|  |       other entities that control, are controlled by, or are under common | ||||||
|  |       control with that entity. For the purposes of this definition, | ||||||
|  |       "control" means (i) the power, direct or indirect, to cause the | ||||||
|  |       direction or management of such entity, whether by contract or | ||||||
|  |       otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||||||
|  |       outstanding shares, or (iii) beneficial ownership of such entity. | ||||||
|  | 
 | ||||||
|  |       "You" (or "Your") shall mean an individual or Legal Entity | ||||||
|  |       exercising permissions granted by this License. | ||||||
|  | 
 | ||||||
|  |       "Source" form shall mean the preferred form for making modifications, | ||||||
|  |       including but not limited to software source code, documentation | ||||||
|  |       source, and configuration files. | ||||||
|  | 
 | ||||||
|  |       "Object" form shall mean any form resulting from mechanical | ||||||
|  |       transformation or translation of a Source form, including but | ||||||
|  |       not limited to compiled object code, generated documentation, | ||||||
|  |       and conversions to other media types. | ||||||
|  | 
 | ||||||
|  |       "Work" shall mean the work of authorship, whether in Source or | ||||||
|  |       Object form, made available under the License, as indicated by a | ||||||
|  |       copyright notice that is included in or attached to the work | ||||||
|  |       (an example is provided in the Appendix below). | ||||||
|  | 
 | ||||||
|  |       "Derivative Works" shall mean any work, whether in Source or Object | ||||||
|  |       form, that is based on (or derived from) the Work and for which the | ||||||
|  |       editorial revisions, annotations, elaborations, or other modifications | ||||||
|  |       represent, as a whole, an original work of authorship. For the purposes | ||||||
|  |       of this License, Derivative Works shall not include works that remain | ||||||
|  |       separable from, or merely link (or bind by name) to the interfaces of, | ||||||
|  |       the Work and Derivative Works thereof. | ||||||
|  | 
 | ||||||
|  |       "Contribution" shall mean any work of authorship, including | ||||||
|  |       the original version of the Work and any modifications or additions | ||||||
|  |       to that Work or Derivative Works thereof, that is intentionally | ||||||
|  |       submitted to Licensor for inclusion in the Work by the copyright owner | ||||||
|  |       or by an individual or Legal Entity authorized to submit on behalf of | ||||||
|  |       the copyright owner. For the purposes of this definition, "submitted" | ||||||
|  |       means any form of electronic, verbal, or written communication sent | ||||||
|  |       to the Licensor or its representatives, including but not limited to | ||||||
|  |       communication on electronic mailing lists, source code control systems, | ||||||
|  |       and issue tracking systems that are managed by, or on behalf of, the | ||||||
|  |       Licensor for the purpose of discussing and improving the Work, but | ||||||
|  |       excluding communication that is conspicuously marked or otherwise | ||||||
|  |       designated in writing by the copyright owner as "Not a Contribution." | ||||||
|  | 
 | ||||||
|  |       "Contributor" shall mean Licensor and any individual or Legal Entity | ||||||
|  |       on behalf of whom a Contribution has been received by Licensor and | ||||||
|  |       subsequently incorporated within the Work. | ||||||
|  | 
 | ||||||
|  |    2. Grant of Copyright License. Subject to the terms and conditions of | ||||||
|  |       this License, each Contributor hereby grants to You a perpetual, | ||||||
|  |       worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||||||
|  |       copyright license to reproduce, prepare Derivative Works of, | ||||||
|  |       publicly display, publicly perform, sublicense, and distribute the | ||||||
|  |       Work and such Derivative Works in Source or Object form. | ||||||
|  | 
 | ||||||
|  |    3. Grant of Patent License. Subject to the terms and conditions of | ||||||
|  |       this License, each Contributor hereby grants to You a perpetual, | ||||||
|  |       worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||||||
|  |       (except as stated in this section) patent license to make, have made, | ||||||
|  |       use, offer to sell, sell, import, and otherwise transfer the Work, | ||||||
|  |       where such license applies only to those patent claims licensable | ||||||
|  |       by such Contributor that are necessarily infringed by their | ||||||
|  |       Contribution(s) alone or by combination of their Contribution(s) | ||||||
|  |       with the Work to which such Contribution(s) was submitted. If You | ||||||
|  |       institute patent litigation against any entity (including a | ||||||
|  |       cross-claim or counterclaim in a lawsuit) alleging that the Work | ||||||
|  |       or a Contribution incorporated within the Work constitutes direct | ||||||
|  |       or contributory patent infringement, then any patent licenses | ||||||
|  |       granted to You under this License for that Work shall terminate | ||||||
|  |       as of the date such litigation is filed. | ||||||
|  | 
 | ||||||
|  |    4. Redistribution. You may reproduce and distribute copies of the | ||||||
|  |       Work or Derivative Works thereof in any medium, with or without | ||||||
|  |       modifications, and in Source or Object form, provided that You | ||||||
|  |       meet the following conditions: | ||||||
|  | 
 | ||||||
|  |       (a) You must give any other recipients of the Work or | ||||||
|  |           Derivative Works a copy of this License; and | ||||||
|  | 
 | ||||||
|  |       (b) You must cause any modified files to carry prominent notices | ||||||
|  |           stating that You changed the files; and | ||||||
|  | 
 | ||||||
|  |       (c) You must retain, in the Source form of any Derivative Works | ||||||
|  |           that You distribute, all copyright, patent, trademark, and | ||||||
|  |           attribution notices from the Source form of the Work, | ||||||
|  |           excluding those notices that do not pertain to any part of | ||||||
|  |           the Derivative Works; and | ||||||
|  | 
 | ||||||
|  |       (d) If the Work includes a "NOTICE" text file as part of its | ||||||
|  |           distribution, then any Derivative Works that You distribute must | ||||||
|  |           include a readable copy of the attribution notices contained | ||||||
|  |           within such NOTICE file, excluding those notices that do not | ||||||
|  |           pertain to any part of the Derivative Works, in at least one | ||||||
|  |           of the following places: within a NOTICE text file distributed | ||||||
|  |           as part of the Derivative Works; within the Source form or | ||||||
|  |           documentation, if provided along with the Derivative Works; or, | ||||||
|  |           within a display generated by the Derivative Works, if and | ||||||
|  |           wherever such third-party notices normally appear. The contents | ||||||
|  |           of the NOTICE file are for informational purposes only and | ||||||
|  |           do not modify the License. You may add Your own attribution | ||||||
|  |           notices within Derivative Works that You distribute, alongside | ||||||
|  |           or as an addendum to the NOTICE text from the Work, provided | ||||||
|  |           that such additional attribution notices cannot be construed | ||||||
|  |           as modifying the License. | ||||||
|  | 
 | ||||||
|  |       You may add Your own copyright statement to Your modifications and | ||||||
|  |       may provide additional or different license terms and conditions | ||||||
|  |       for use, reproduction, or distribution of Your modifications, or | ||||||
|  |       for any such Derivative Works as a whole, provided Your use, | ||||||
|  |       reproduction, and distribution of the Work otherwise complies with | ||||||
|  |       the conditions stated in this License. | ||||||
|  | 
 | ||||||
|  |    5. Submission of Contributions. Unless You explicitly state otherwise, | ||||||
|  |       any Contribution intentionally submitted for inclusion in the Work | ||||||
|  |       by You to the Licensor shall be under the terms and conditions of | ||||||
|  |       this License, without any additional terms or conditions. | ||||||
|  |       Notwithstanding the above, nothing herein shall supersede or modify | ||||||
|  |       the terms of any separate license agreement you may have executed | ||||||
|  |       with Licensor regarding such Contributions. | ||||||
|  | 
 | ||||||
|  |    6. Trademarks. This License does not grant permission to use the trade | ||||||
|  |       names, trademarks, service marks, or product names of the Licensor, | ||||||
|  |       except as required for reasonable and customary use in describing the | ||||||
|  |       origin of the Work and reproducing the content of the NOTICE file. | ||||||
|  | 
 | ||||||
|  |    7. Disclaimer of Warranty. Unless required by applicable law or | ||||||
|  |       agreed to in writing, Licensor provides the Work (and each | ||||||
|  |       Contributor provides its Contributions) on an "AS IS" BASIS, | ||||||
|  |       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | ||||||
|  |       implied, including, without limitation, any warranties or conditions | ||||||
|  |       of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | ||||||
|  |       PARTICULAR PURPOSE. You are solely responsible for determining the | ||||||
|  |       appropriateness of using or redistributing the Work and assume any | ||||||
|  |       risks associated with Your exercise of permissions under this License. | ||||||
|  | 
 | ||||||
|  |    8. Limitation of Liability. In no event and under no legal theory, | ||||||
|  |       whether in tort (including negligence), contract, or otherwise, | ||||||
|  |       unless required by applicable law (such as deliberate and grossly | ||||||
|  |       negligent acts) or agreed to in writing, shall any Contributor be | ||||||
|  |       liable to You for damages, including any direct, indirect, special, | ||||||
|  |       incidental, or consequential damages of any character arising as a | ||||||
|  |       result of this License or out of the use or inability to use the | ||||||
|  |       Work (including but not limited to damages for loss of goodwill, | ||||||
|  |       work stoppage, computer failure or malfunction, or any and all | ||||||
|  |       other commercial damages or losses), even if such Contributor | ||||||
|  |       has been advised of the possibility of such damages. | ||||||
|  | 
 | ||||||
|  |    9. Accepting Warranty or Additional Liability. While redistributing | ||||||
|  |       the Work or Derivative Works thereof, You may choose to offer, | ||||||
|  |       and charge a fee for, acceptance of support, warranty, indemnity, | ||||||
|  |       or other liability obligations and/or rights consistent with this | ||||||
|  |       License. However, in accepting such obligations, You may act only | ||||||
|  |       on Your own behalf and on Your sole responsibility, not on behalf | ||||||
|  |       of any other Contributor, and only if You agree to indemnify, | ||||||
|  |       defend, and hold each Contributor harmless for any liability | ||||||
|  |       incurred by, or claims asserted against, such Contributor by reason | ||||||
|  |       of your accepting any such warranty or additional liability. | ||||||
|  | 
 | ||||||
|  |    END OF TERMS AND CONDITIONS | ||||||
|  | 
 | ||||||
|  |    APPENDIX: How to apply the Apache License to your work. | ||||||
|  | 
 | ||||||
|  |       To apply the Apache License to your work, attach the following | ||||||
|  |       boilerplate notice, with the fields enclosed by brackets "[]" | ||||||
|  |       replaced with your own identifying information. (Don't include | ||||||
|  |       the brackets!)  The text should be enclosed in the appropriate | ||||||
|  |       comment syntax for the file format. We also recommend that a | ||||||
|  |       file or class name and description of purpose be included on the | ||||||
|  |       same "printed page" as the copyright notice for easier | ||||||
|  |       identification within third-party archives. | ||||||
|  | 
 | ||||||
|  |    Copyright 2020 k8s@Home | ||||||
|  | 
 | ||||||
|  |    Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  |    you may not use this file except in compliance with the License. | ||||||
|  |    You may obtain a copy of the License at | ||||||
|  | 
 | ||||||
|  |        http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  | 
 | ||||||
|  |    Unless required by applicable law or agreed to in writing, software | ||||||
|  |    distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  |    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  |    See the License for the specific language governing permissions and | ||||||
|  |    limitations under the License. | ||||||
							
								
								
									
										50
									
								
								charts/paperless-ngx/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,50 @@ | |||||||
|  | # paperless | ||||||
|  | 
 | ||||||
|  |   | ||||||
|  | 
 | ||||||
|  | Paperless-ngx - Index and archive all of your scanned paper documents | ||||||
|  | 
 | ||||||
|  | **Homepage:** <https://github.com/paperless-ngx/paperless-ngx/tree/main/charts/paperless-ngx> | ||||||
|  | 
 | ||||||
|  | ## Maintainers | ||||||
|  | 
 | ||||||
|  | | Name | Email | Url | | ||||||
|  | | ---- | ------ | --- | | ||||||
|  | | Paperless-ngx maintainers |  |  | | ||||||
|  | 
 | ||||||
|  | ## Source Code | ||||||
|  | 
 | ||||||
|  | * <https://github.com/paperless-ngx/paperless-ngx> | ||||||
|  | 
 | ||||||
|  | ## Requirements | ||||||
|  | 
 | ||||||
|  | Kubernetes: `>=1.16.0-0` | ||||||
|  | 
 | ||||||
|  | | Repository | Name | Version | | ||||||
|  | |------------|------|---------| | ||||||
|  | | https://charts.bitnami.com/bitnami | postgresql | 11.6.12 | | ||||||
|  | | https://charts.bitnami.com/bitnami | redis | 16.13.1 | | ||||||
|  | | https://library-charts.k8s-at-home.com | common | 4.5.2 | | ||||||
|  | 
 | ||||||
|  | ## Values | ||||||
|  | 
 | ||||||
|  | | Key | Type | Default | Description | | ||||||
|  | |-----|------|---------|-------------| | ||||||
|  | | env | object | See below | See the following files for additional environment variables: https://github.com/paperless-ngx/paperless-ngx/tree/main/docker/compose/ https://github.com/paperless-ngx/paperless-ngx/blob/main/paperless.conf.example | | ||||||
|  | | env.COMPOSE_PROJECT_NAME | string | `"paperless"` | Project name | | ||||||
|  | | env.PAPERLESS_DBHOST | string | `nil` | Database host to use | | ||||||
|  | | env.PAPERLESS_OCR_LANGUAGE | string | `"eng"` | OCR languages to install | | ||||||
|  | | env.PAPERLESS_PORT | int | `8000` | Port to use | | ||||||
|  | | env.PAPERLESS_REDIS | string | `nil` | Redis to use | | ||||||
|  | | image.pullPolicy | string | `"IfNotPresent"` | image pull policy | | ||||||
|  | | image.repository | string | `"ghcr.io/paperless-ngx/paperless-ngx"` | image repository | | ||||||
|  | | image.tag | string | chart.appVersion | image tag | | ||||||
|  | | ingress.main | object | See values.yaml | Enable and configure ingress settings for the chart under this key. | | ||||||
|  | | persistence.consume | object | See values.yaml | Configure volume to monitor for new documents. | | ||||||
|  | | persistence.data | object | See values.yaml | Configure persistence for data. | | ||||||
|  | | persistence.export | object | See values.yaml | Configure export volume. | | ||||||
|  | | persistence.media | object | See values.yaml | Configure persistence for media. | | ||||||
|  | | postgresql | object | See values.yaml | Enable and configure postgresql database subchart under this key.    For more options see [postgresql chart documentation](https://github.com/bitnami/charts/tree/master/bitnami/postgresql) | | ||||||
|  | | redis | object | See values.yaml | Enable and configure redis subchart under this key.    For more options see [redis chart documentation](https://github.com/bitnami/charts/tree/master/bitnami/redis) | | ||||||
|  | | service | object | See values.yaml | Configures service settings for the chart. | | ||||||
|  | 
 | ||||||
							
								
								
									
										8
									
								
								charts/paperless-ngx/README_CONFIG.md.gotmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,8 @@ | |||||||
|  | {{- define "custom.custom.configuration.header" -}} | ||||||
|  | ## Custom configuration | ||||||
|  | {{- end -}} | ||||||
|  | 
 | ||||||
|  | {{- define "custom.custom.configuration" -}} | ||||||
|  | {{ template "custom.custom.configuration.header" . }} | ||||||
|  | N/A | ||||||
|  | {{- end -}} | ||||||
							
								
								
									
										26
									
								
								charts/paperless-ngx/ci/ct-values.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,26 @@ | |||||||
|  | env: | ||||||
|  |   PAPERLESS_REDIS: redis://paperless-redis-headless:6379 | ||||||
|  | 
 | ||||||
|  | persistence: | ||||||
|  |   data: | ||||||
|  |     enabled: true | ||||||
|  |     type: emptyDir | ||||||
|  |   media: | ||||||
|  |     enabled: true | ||||||
|  |     type: emptyDir | ||||||
|  |   consume: | ||||||
|  |     enabled: true | ||||||
|  |     type: emptyDir | ||||||
|  |   export: | ||||||
|  |     enabled: true | ||||||
|  |     type: emptyDir | ||||||
|  | 
 | ||||||
|  | redis: | ||||||
|  |   enabled: true | ||||||
|  |   architecture: standalone | ||||||
|  |   auth: | ||||||
|  |     enabled: false | ||||||
|  |   master: | ||||||
|  |     persistence: | ||||||
|  |       enabled: false | ||||||
|  |   fullnameOverride: paperless-redis | ||||||
							
								
								
									
										4
									
								
								charts/paperless-ngx/templates/NOTES.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,4 @@ | |||||||
|  | {{- include "common.notes.defaultNotes" . }} | ||||||
|  | 2. Create a super user by running the command: | ||||||
|  |   export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "common.names.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") | ||||||
|  |   kubectl exec -it --namespace {{ .Release.Namespace }} $POD_NAME -- bash -c "python manage.py createsuperuser" | ||||||
							
								
								
									
										11
									
								
								charts/paperless-ngx/templates/common.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,11 @@ | |||||||
|  | {{/* Make sure all variables are set properly */}} | ||||||
|  | {{- include "common.values.setup" . }} | ||||||
|  | 
 | ||||||
|  | {{/* Append the hardcoded settings */}} | ||||||
|  | {{- define "paperless.harcodedValues" -}} | ||||||
|  | env: | ||||||
|  |     PAPERLESS_URL: http{{if ne ( len .Values.ingress.main.tls ) 0 }}s{{end}}://{{ (first .Values.ingress.main.hosts).host }} | ||||||
|  | {{- end -}} | ||||||
|  | {{- $_ := merge .Values (include "paperless.harcodedValues" . | fromYaml) -}} | ||||||
|  | 
 | ||||||
|  | {{ include "common.all" . }} | ||||||
							
								
								
									
										107
									
								
								charts/paperless-ngx/values.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,107 @@ | |||||||
|  | # | ||||||
|  | # IMPORTANT NOTE | ||||||
|  | # | ||||||
|  | # This chart inherits from our common library chart. You can check the default values/options here: | ||||||
|  | # https://github.com/k8s-at-home/library-charts/tree/main/charts/stable/common/values.yaml | ||||||
|  | # | ||||||
|  | 
 | ||||||
|  | image: | ||||||
|  |   # -- image repository | ||||||
|  |   repository: ghcr.io/paperless-ngx/paperless-ngx | ||||||
|  |   # -- image pull policy | ||||||
|  |   pullPolicy: IfNotPresent | ||||||
|  |   # -- image tag | ||||||
|  |   # @default -- chart.appVersion | ||||||
|  |   tag: | ||||||
|  | 
 | ||||||
|  | # -- See the following files for additional environment variables: | ||||||
|  | # https://github.com/paperless-ngx/paperless-ngx/tree/main/docker/compose/ | ||||||
|  | # https://github.com/paperless-ngx/paperless-ngx/blob/main/paperless.conf.example | ||||||
|  | # @default -- See below | ||||||
|  | env: | ||||||
|  |   # -- Project name | ||||||
|  |   COMPOSE_PROJECT_NAME: paperless | ||||||
|  |   # -- Redis to use | ||||||
|  |   PAPERLESS_REDIS: | ||||||
|  |   # -- OCR languages to install | ||||||
|  |   PAPERLESS_OCR_LANGUAGE: eng | ||||||
|  |   # USERMAP_UID: 1000 | ||||||
|  |   # USERMAP_GID: 1000 | ||||||
|  |   # PAPERLESS_TIME_ZONE: Europe/London | ||||||
|  |   # -- Database host to use | ||||||
|  |   PAPERLESS_DBHOST: | ||||||
|  |   # -- Port to use | ||||||
|  |   PAPERLESS_PORT: 8000 | ||||||
|  |   # -- Username for the root user | ||||||
|  |   # PAPERLESS_ADMIN_USER: admin | ||||||
|  |   # -- Password for the root user | ||||||
|  |   # PAPERLESS_ADMIN_PASSWORD: admin | ||||||
|  |   # PAPERLESS_URL: <set to main ingress by default> | ||||||
|  | 
 | ||||||
|  | # -- Configures service settings for the chart. | ||||||
|  | # @default -- See values.yaml | ||||||
|  | service: | ||||||
|  |   main: | ||||||
|  |     ports: | ||||||
|  |       http: | ||||||
|  |         port: 8000 | ||||||
|  | 
 | ||||||
|  | ingress: | ||||||
|  |   # -- Enable and configure ingress settings for the chart under this key. | ||||||
|  |   # @default -- See values.yaml | ||||||
|  |   main: | ||||||
|  |     enabled: false | ||||||
|  | 
 | ||||||
|  | persistence: | ||||||
|  |   # -- Configure persistence for data. | ||||||
|  |   # @default -- See values.yaml | ||||||
|  |   data: | ||||||
|  |     enabled: false | ||||||
|  |     mountPath: /usr/src/paperless/data | ||||||
|  |     accessMode: ReadWriteOnce | ||||||
|  |     emptyDir: | ||||||
|  |       enabled: false | ||||||
|  |   # -- Configure persistence for media. | ||||||
|  |   # @default -- See values.yaml | ||||||
|  |   media: | ||||||
|  |     enabled: false | ||||||
|  |     mountPath: /usr/src/paperless/media | ||||||
|  |     accessMode: ReadWriteOnce | ||||||
|  |     emptyDir: | ||||||
|  |       enabled: false | ||||||
|  |   # -- Configure volume to monitor for new documents. | ||||||
|  |   # @default -- See values.yaml | ||||||
|  |   consume: | ||||||
|  |     enabled: false | ||||||
|  |     mountPath: /usr/src/paperless/consume | ||||||
|  |     accessMode: ReadWriteOnce | ||||||
|  |     emptyDir: | ||||||
|  |       enabled: false | ||||||
|  |   # -- Configure export volume. | ||||||
|  |   # @default -- See values.yaml | ||||||
|  |   export: | ||||||
|  |     enabled: false | ||||||
|  |     mountPath: /usr/src/paperless/export | ||||||
|  |     accessMode: ReadWriteOnce | ||||||
|  |     emptyDir: | ||||||
|  |       enabled: false | ||||||
|  | 
 | ||||||
|  | # -- Enable and configure postgresql database subchart under this key. | ||||||
|  | #    For more options see [postgresql chart documentation](https://github.com/bitnami/charts/tree/master/bitnami/postgresql) | ||||||
|  | # @default -- See values.yaml | ||||||
|  | postgresql: | ||||||
|  |   enabled: false | ||||||
|  |   postgresqlUsername: paperless | ||||||
|  |   postgresqlPassword: paperless | ||||||
|  |   postgresqlDatabase: paperless | ||||||
|  |   persistence: | ||||||
|  |     enabled: false | ||||||
|  |     # storageClass: "" | ||||||
|  | 
 | ||||||
|  | # -- Enable and configure redis subchart under this key. | ||||||
|  | #    For more options see [redis chart documentation](https://github.com/bitnami/charts/tree/master/bitnami/redis) | ||||||
|  | # @default -- See values.yaml | ||||||
|  | redis: | ||||||
|  |   enabled: false | ||||||
|  |   auth: | ||||||
|  |     enabled: false | ||||||
							
								
								
									
										25
									
								
								docker/compose/docker-compose.ci-test.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,25 @@ | |||||||
|  | # docker-compose file for running paperless testing with actual gotenberg | ||||||
|  | # and Tika containers for a more end to end test of the Tika related functionality | ||||||
|  | # Can be used locally or by the CI to start the nessecary containers with the | ||||||
|  | # correct networking for the tests | ||||||
|  | 
 | ||||||
|  | version: "3.7" | ||||||
|  | services: | ||||||
|  |   gotenberg: | ||||||
|  |     image: docker.io/gotenberg/gotenberg:7.6 | ||||||
|  |     hostname: gotenberg | ||||||
|  |     container_name: gotenberg | ||||||
|  |     network_mode: host | ||||||
|  |     restart: unless-stopped | ||||||
|  |     # The gotenberg chromium route is used to convert .eml files. We do not | ||||||
|  |     # want to allow external content like tracking pixels or even javascript. | ||||||
|  |     command: | ||||||
|  |       - "gotenberg" | ||||||
|  |       - "--chromium-disable-javascript=true" | ||||||
|  |       - "--chromium-allow-list=file:///tmp/.*" | ||||||
|  |   tika: | ||||||
|  |     image: ghcr.io/paperless-ngx/tika:latest | ||||||
|  |     hostname: tika | ||||||
|  |     container_name: tika | ||||||
|  |     network_mode: host | ||||||
|  |     restart: unless-stopped | ||||||
| @ -77,8 +77,8 @@ services: | |||||||
|       PAPERLESS_REDIS: redis://broker:6379 |       PAPERLESS_REDIS: redis://broker:6379 | ||||||
|       PAPERLESS_DBENGINE: mariadb |       PAPERLESS_DBENGINE: mariadb | ||||||
|       PAPERLESS_DBHOST: db |       PAPERLESS_DBHOST: db | ||||||
|       PAPERLESS_DBUSER: paperless |       PAPERLESS_DBUSER: paperless # only needed if non-default username | ||||||
|       PAPERLESS_DBPASSWORD: paperless |       PAPERLESS_DBPASS: paperless # only needed if non-default password | ||||||
|       PAPERLESS_DBPORT: 3306 |       PAPERLESS_DBPORT: 3306 | ||||||
|       PAPERLESS_TIKA_ENABLED: 1 |       PAPERLESS_TIKA_ENABLED: 1 | ||||||
|       PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000 |       PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000 | ||||||
| @ -87,9 +87,12 @@ services: | |||||||
|   gotenberg: |   gotenberg: | ||||||
|     image: docker.io/gotenberg/gotenberg:7.6 |     image: docker.io/gotenberg/gotenberg:7.6 | ||||||
|     restart: unless-stopped |     restart: unless-stopped | ||||||
|  |     # The gotenberg chromium route is used to convert .eml files. We do not | ||||||
|  |     # want to allow external content like tracking pixels or even javascript. | ||||||
|     command: |     command: | ||||||
|       - "gotenberg" |       - "gotenberg" | ||||||
|       - "--chromium-disable-routes=true" |       - "--chromium-disable-javascript=true" | ||||||
|  |       - "--chromium-allow-list=file:///tmp/.*" | ||||||
| 
 | 
 | ||||||
|   tika: |   tika: | ||||||
|     image: ghcr.io/paperless-ngx/tika:latest |     image: ghcr.io/paperless-ngx/tika:latest | ||||||
|  | |||||||
| @ -71,8 +71,8 @@ services: | |||||||
|       PAPERLESS_REDIS: redis://broker:6379 |       PAPERLESS_REDIS: redis://broker:6379 | ||||||
|       PAPERLESS_DBENGINE: mariadb |       PAPERLESS_DBENGINE: mariadb | ||||||
|       PAPERLESS_DBHOST: db |       PAPERLESS_DBHOST: db | ||||||
|       PAPERLESS_DBUSER: paperless |       PAPERLESS_DBUSER: paperless # only needed if non-default username | ||||||
|       PAPERLESS_DBPASSWORD: paperless |       PAPERLESS_DBPASS: paperless # only needed if non-default password | ||||||
|       PAPERLESS_DBPORT: 3306 |       PAPERLESS_DBPORT: 3306 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -79,9 +79,13 @@ services: | |||||||
|   gotenberg: |   gotenberg: | ||||||
|     image: docker.io/gotenberg/gotenberg:7.6 |     image: docker.io/gotenberg/gotenberg:7.6 | ||||||
|     restart: unless-stopped |     restart: unless-stopped | ||||||
|  | 
 | ||||||
|  |     # The gotenberg chromium route is used to convert .eml files. We do not | ||||||
|  |     # want to allow external content like tracking pixels or even javascript. | ||||||
|     command: |     command: | ||||||
|       - "gotenberg" |       - "gotenberg" | ||||||
|       - "--chromium-disable-routes=true" |       - "--chromium-disable-javascript=true" | ||||||
|  |       - "--chromium-allow-list=file:///tmp/.*" | ||||||
| 
 | 
 | ||||||
|   tika: |   tika: | ||||||
|     image: ghcr.io/paperless-ngx/tika:latest |     image: ghcr.io/paperless-ngx/tika:latest | ||||||
|  | |||||||
| @ -67,9 +67,13 @@ services: | |||||||
|   gotenberg: |   gotenberg: | ||||||
|     image: docker.io/gotenberg/gotenberg:7.6 |     image: docker.io/gotenberg/gotenberg:7.6 | ||||||
|     restart: unless-stopped |     restart: unless-stopped | ||||||
|  | 
 | ||||||
|  |     # The gotenberg chromium route is used to convert .eml files. We do not | ||||||
|  |     # want to allow external content like tracking pixels or even javascript. | ||||||
|     command: |     command: | ||||||
|       - "gotenberg" |       - "gotenberg" | ||||||
|       - "--chromium-disable-routes=true" |       - "--chromium-disable-javascript=true" | ||||||
|  |       - "--chromium-allow-list=file:///tmp/.*" | ||||||
| 
 | 
 | ||||||
|   tika: |   tika: | ||||||
|     image: ghcr.io/paperless-ngx/tika:latest |     image: ghcr.io/paperless-ngx/tika:latest | ||||||
|  | |||||||
| @ -77,6 +77,46 @@ nltk_data () { | |||||||
| 
 | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | custom_container_init() { | ||||||
|  | 	# Mostly borrowed from the LinuxServer.io base image | ||||||
|  | 	# https://github.com/linuxserver/docker-baseimage-ubuntu/tree/bionic/root/etc/cont-init.d | ||||||
|  | 	local -r custom_script_dir="/custom-cont-init.d" | ||||||
|  | 	# Tamper checking. | ||||||
|  | 	# Don't run files which are owned by anyone except root | ||||||
|  | 	# Don't run files which are writeable by others | ||||||
|  | 	if [ -d "${custom_script_dir}" ]; then | ||||||
|  | 		if [ -n "$(/usr/bin/find "${custom_script_dir}" -maxdepth 1 ! -user root)" ]; then | ||||||
|  | 			echo "**** Potential tampering with custom scripts detected ****" | ||||||
|  | 			echo "**** The folder '${custom_script_dir}' must be owned by root ****" | ||||||
|  | 			return 0 | ||||||
|  | 		fi | ||||||
|  | 		if [ -n "$(/usr/bin/find "${custom_script_dir}" -maxdepth 1 -perm -o+w)" ]; then | ||||||
|  | 			echo "**** The folder '${custom_script_dir}' or some of contents have write permissions for others, which is a security risk. ****" | ||||||
|  | 			echo "**** Please review the permissions and their contents to make sure they are owned by root, and can only be modified by root. ****" | ||||||
|  | 			return 0 | ||||||
|  | 		fi | ||||||
|  | 
 | ||||||
|  | 		# Make sure custom init directory has files in it | ||||||
|  | 		if [ -n "$(/bin/ls -A "${custom_script_dir}" 2>/dev/null)" ]; then | ||||||
|  | 			echo "[custom-init] files found in ${custom_script_dir} executing" | ||||||
|  | 			# Loop over files in the directory | ||||||
|  | 			for SCRIPT in "${custom_script_dir}"/*; do | ||||||
|  | 				NAME="$(basename "${SCRIPT}")" | ||||||
|  | 				if [ -f "${SCRIPT}" ]; then | ||||||
|  | 					echo "[custom-init] ${NAME}: executing..." | ||||||
|  | 					/bin/bash "${SCRIPT}" | ||||||
|  | 					echo "[custom-init] ${NAME}: exited $?" | ||||||
|  | 				elif [ ! -f "${SCRIPT}" ]; then | ||||||
|  | 					echo "[custom-init] ${NAME}: is not a file" | ||||||
|  | 				fi | ||||||
|  | 			done | ||||||
|  | 		else | ||||||
|  | 			echo "[custom-init] no custom files found exiting..." | ||||||
|  | 		fi | ||||||
|  | 
 | ||||||
|  | 	fi | ||||||
|  | } | ||||||
|  | 
 | ||||||
| initialize() { | initialize() { | ||||||
| 
 | 
 | ||||||
| 	# Setup environment from secrets before anything else | 	# Setup environment from secrets before anything else | ||||||
| @ -132,13 +172,16 @@ initialize() { | |||||||
| 	set -e | 	set -e | ||||||
| 
 | 
 | ||||||
| 	"${gosu_cmd[@]}" /sbin/docker-prepare.sh | 	"${gosu_cmd[@]}" /sbin/docker-prepare.sh | ||||||
|  | 
 | ||||||
|  | 	# Leave this last thing | ||||||
|  | 	custom_container_init | ||||||
|  | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| install_languages() { | install_languages() { | ||||||
| 	echo "Installing languages..." | 	echo "Installing languages..." | ||||||
| 
 | 
 | ||||||
| 	local -r langs="$1" | 	read -ra langs <<<"$1" | ||||||
| 	read -ra langs <<<"$langs" |  | ||||||
| 
 | 
 | ||||||
| 	# Check that it is not empty | 	# Check that it is not empty | ||||||
| 	if [ ${#langs[@]} -eq 0 ]; then | 	if [ ${#langs[@]} -eq 0 ]; then | ||||||
|  | |||||||
| @ -89,46 +89,6 @@ superuser() { | |||||||
| 	fi | 	fi | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| custom_container_init() { |  | ||||||
| 	# Mostly borrowed from the LinuxServer.io base image |  | ||||||
| 	# https://github.com/linuxserver/docker-baseimage-ubuntu/tree/bionic/root/etc/cont-init.d |  | ||||||
| 	local -r custom_script_dir="/custom-cont-init.d" |  | ||||||
| 	# Tamper checking. |  | ||||||
| 	# Don't run files which are owned by anyone except root |  | ||||||
| 	# Don't run files which are writeable by others |  | ||||||
| 	if [ -d "${custom_script_dir}" ]; then |  | ||||||
| 		if [ -n "$(/usr/bin/find "${custom_script_dir}" -maxdepth 1 ! -user root)" ]; then |  | ||||||
| 			echo "**** Potential tampering with custom scripts detected ****" |  | ||||||
| 			echo "**** The folder '${custom_script_dir}' must be owned by root ****" |  | ||||||
| 			return 0 |  | ||||||
| 		fi |  | ||||||
| 		if [ -n "$(/usr/bin/find "${custom_script_dir}" -maxdepth 1 -perm -o+w)" ]; then |  | ||||||
| 			echo "**** The folder '${custom_script_dir}' or some of contents have write permissions for others, which is a security risk. ****" |  | ||||||
| 			echo "**** Please review the permissions and their contents to make sure they are owned by root, and can only be modified by root. ****" |  | ||||||
| 			return 0 |  | ||||||
| 		fi |  | ||||||
| 
 |  | ||||||
| 		# Make sure custom init directory has files in it |  | ||||||
| 		if [ -n "$(/bin/ls -A "${custom_script_dir}" 2>/dev/null)" ]; then |  | ||||||
| 			echo "[custom-init] files found in ${custom_script_dir} executing" |  | ||||||
| 			# Loop over files in the directory |  | ||||||
| 			for SCRIPT in "${custom_script_dir}"/*; do |  | ||||||
| 				NAME="$(basename "${SCRIPT}")" |  | ||||||
| 				if [ -f "${SCRIPT}" ]; then |  | ||||||
| 					echo "[custom-init] ${NAME}: executing..." |  | ||||||
| 					/bin/bash "${SCRIPT}" |  | ||||||
| 					echo "[custom-init] ${NAME}: exited $?" |  | ||||||
| 				elif [ ! -f "${SCRIPT}" ]; then |  | ||||||
| 					echo "[custom-init] ${NAME}: is not a file" |  | ||||||
| 				fi |  | ||||||
| 			done |  | ||||||
| 		else |  | ||||||
| 			echo "[custom-init] no custom files found exiting..." |  | ||||||
| 		fi |  | ||||||
| 
 |  | ||||||
| 	fi |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| do_work() { | do_work() { | ||||||
| 	if [[ "${PAPERLESS_DBENGINE}" == "mariadb" ]]; then | 	if [[ "${PAPERLESS_DBENGINE}" == "mariadb" ]]; then | ||||||
| 		wait_for_mariadb | 		wait_for_mariadb | ||||||
| @ -144,9 +104,6 @@ do_work() { | |||||||
| 
 | 
 | ||||||
| 	superuser | 	superuser | ||||||
| 
 | 
 | ||||||
| 	# Leave this last thing |  | ||||||
| 	custom_container_init |  | ||||||
| 
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| do_work | do_work | ||||||
|  | |||||||
							
								
								
									
										181
									
								
								docs/Makefile
									
									
									
									
									
								
							
							
						
						| @ -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." |  | ||||||
							
								
								
									
										597
									
								
								docs/_static/css/custom.css
									
									
									
									
										vendored
									
									
								
							
							
						
						| @ -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; |  | ||||||
| } |  | ||||||
							
								
								
									
										47
									
								
								docs/_static/js/darkmode.js
									
									
									
									
										vendored
									
									
								
							
							
						
						| @ -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) |  | ||||||
							
								
								
									
										
											BIN
										
									
								
								docs/_static/screenshots/mail-rules-edited.png
									
									
									
									
										vendored
									
									
								
							
							
						
						| Before Width: | Height: | Size: 96 KiB | 
							
								
								
									
										13
									
								
								docs/_templates/layout.html
									
									
									
									
										vendored
									
									
								
							
							
						
						| @ -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 %} |  | ||||||
							
								
								
									
										502
									
								
								docs/administration.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,502 @@ | |||||||
|  | # 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](#management-commands). | ||||||
|  | 
 | ||||||
|  | ### 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] | ||||||
|  | ``` | ||||||
| @ -1,523 +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. |  | ||||||
| 
 |  | ||||||
| .. _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] |  | ||||||
							
								
								
									
										468
									
								
								docs/advanced_usage.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,468 @@ | |||||||
|  | # 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 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]{.title-ref} 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: | ||||||
|  | 
 | ||||||
|  | ```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;` | ||||||
| @ -1,419 +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. |  | ||||||
| 
 |  | ||||||
| .. _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. |  | ||||||
| 
 |  | ||||||
| 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 and its contents must be owned by `root`. |  | ||||||
| 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. |  | ||||||
| This is an advanced functionality with which you could break functionality or lose data. |  | ||||||
| 
 |  | ||||||
| For example, using Docker Compose: |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| .. code:: yaml |  | ||||||
| 
 |  | ||||||
|     services: |  | ||||||
|       # ... |  | ||||||
|       webserver: |  | ||||||
|         # ... |  | ||||||
|         volumes: |  | ||||||
|           - /path/to/my/scripts:/custom-cont-init.d:ro |  | ||||||
							
								
								
									
										318
									
								
								docs/api.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,318 @@ | |||||||
|  | # 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](usage#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: | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | { | ||||||
|  |     "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 {#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`. | ||||||
							
								
								
									
										303
									
								
								docs/api.rst
									
									
									
									
									
								
							
							
						
						| @ -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
									
								
							
							
						
						| @ -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; | ||||||
|  | } | ||||||
							
								
								
									
										
											BIN
										
									
								
								docs/assets/favicon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 768 B | 
							
								
								
									
										12
									
								
								docs/assets/logo.svg
									
									
									
									
									
										Normal 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 | 
							
								
								
									
										68
									
								
								docs/assets/logo_full_black.svg
									
									
									
									
									
										Normal 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 | 
							
								
								
									
										69
									
								
								docs/assets/logo_full_white.svg
									
									
									
									
									
										Normal 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 | 
| Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 67 KiB | 
| Before Width: | Height: | Size: 661 KiB After Width: | Height: | Size: 661 KiB | 
| Before Width: | Height: | Size: 457 KiB After Width: | Height: | Size: 457 KiB | 
| Before Width: | Height: | Size: 436 KiB After Width: | Height: | Size: 436 KiB | 
| Before Width: | Height: | Size: 462 KiB After Width: | Height: | Size: 462 KiB | 
| Before Width: | Height: | Size: 608 KiB After Width: | Height: | Size: 608 KiB | 
| Before Width: | Height: | Size: 698 KiB After Width: | Height: | Size: 698 KiB | 
| Before Width: | Height: | Size: 706 KiB After Width: | Height: | Size: 706 KiB | 
| Before Width: | Height: | Size: 480 KiB After Width: | Height: | Size: 480 KiB | 
| Before Width: | Height: | Size: 680 KiB After Width: | Height: | Size: 680 KiB | 
| Before Width: | Height: | Size: 686 KiB After Width: | Height: | Size: 686 KiB | 
| Before Width: | Height: | Size: 848 KiB After Width: | Height: | Size: 848 KiB | 
| Before Width: | Height: | Size: 703 KiB After Width: | Height: | Size: 703 KiB | 
							
								
								
									
										
											BIN
										
									
								
								docs/assets/screenshots/mail-rules-edited.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 76 KiB | 
| Before Width: | Height: | Size: 388 KiB After Width: | Height: | Size: 388 KiB | 
| Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB | 
| Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB | 
| Before Width: | Height: | Size: 517 KiB After Width: | Height: | Size: 517 KiB | 
| @ -1,7 +1,230 @@ | |||||||
| # Changelog | # Changelog | ||||||
| 
 | 
 | ||||||
|  | ## paperless-ngx 1.10.1 | ||||||
|  | 
 | ||||||
|  | ### Features | ||||||
|  | 
 | ||||||
|  | - Feature: Allows documents in WebP format [@stumpylog](https://github.com/stumpylog) ([#1984](https://github.com/paperless-ngx/paperless-ngx/pull/1984)) | ||||||
|  | 
 | ||||||
|  | ### Bug Fixes | ||||||
|  | 
 | ||||||
|  | - Fix: frontend tasks display in 1.10.0 [@shamoon](https://github.com/shamoon) ([#2073](https://github.com/paperless-ngx/paperless-ngx/pull/2073)) | ||||||
|  | - Bugfix: Custom startup commands weren't run as root [@stumpylog](https://github.com/stumpylog) ([#2069](https://github.com/paperless-ngx/paperless-ngx/pull/2069)) | ||||||
|  | - Bugfix: Add libatomic for armv7 compatibility [@stumpylog](https://github.com/stumpylog) ([#2066](https://github.com/paperless-ngx/paperless-ngx/pull/2066)) | ||||||
|  | - Bugfix: Don't silence an exception when trying to handle file naming [@stumpylog](https://github.com/stumpylog) ([#2062](https://github.com/paperless-ngx/paperless-ngx/pull/2062)) | ||||||
|  | - Bugfix: Some tesseract languages aren't detected as installed. [@stumpylog](https://github.com/stumpylog) ([#2057](https://github.com/paperless-ngx/paperless-ngx/pull/2057)) | ||||||
|  | 
 | ||||||
|  | ### Maintenance | ||||||
|  | 
 | ||||||
|  | - Chore: Use a maintained upload-release-asset [@stumpylog](https://github.com/stumpylog) ([#2055](https://github.com/paperless-ngx/paperless-ngx/pull/2055)) | ||||||
|  | 
 | ||||||
|  | ### Dependencies | ||||||
|  | 
 | ||||||
|  |   <details> | ||||||
|  |   <summary>5 changes</summary> | ||||||
|  | 
 | ||||||
|  | - Bump tslib from 2.4.0 to 2.4.1 in /src-ui @dependabot ([#2076](https://github.com/paperless-ngx/paperless-ngx/pull/2076)) | ||||||
|  | - Bump @<!---->angular-builders/jest from 14.0.1 to 14.1.0 in /src-ui @dependabot ([#2079](https://github.com/paperless-ngx/paperless-ngx/pull/2079)) | ||||||
|  | - Bump jest-preset-angular from 12.2.2 to 12.2.3 in /src-ui @dependabot ([#2078](https://github.com/paperless-ngx/paperless-ngx/pull/2078)) | ||||||
|  | - Bump ngx-file-drop from 14.0.1 to 14.0.2 in /src-ui @dependabot ([#2080](https://github.com/paperless-ngx/paperless-ngx/pull/2080)) | ||||||
|  | - Bump @<!---->ngneat/dirty-check-forms from 3.0.2 to 3.0.3 in /src-ui @dependabot ([#2077](https://github.com/paperless-ngx/paperless-ngx/pull/2077)) | ||||||
|  | </details> | ||||||
|  | 
 | ||||||
|  | ### All App Changes | ||||||
|  | 
 | ||||||
|  | - Bump tslib from 2.4.0 to 2.4.1 in /src-ui @dependabot ([#2076](https://github.com/paperless-ngx/paperless-ngx/pull/2076)) | ||||||
|  | - Bump @<!---->angular-builders/jest from 14.0.1 to 14.1.0 in /src-ui @dependabot ([#2079](https://github.com/paperless-ngx/paperless-ngx/pull/2079)) | ||||||
|  | - Bump jest-preset-angular from 12.2.2 to 12.2.3 in /src-ui @dependabot ([#2078](https://github.com/paperless-ngx/paperless-ngx/pull/2078)) | ||||||
|  | - Bump ngx-file-drop from 14.0.1 to 14.0.2 in /src-ui @dependabot ([#2080](https://github.com/paperless-ngx/paperless-ngx/pull/2080)) | ||||||
|  | - Bump @<!---->ngneat/dirty-check-forms from 3.0.2 to 3.0.3 in /src-ui @dependabot ([#2077](https://github.com/paperless-ngx/paperless-ngx/pull/2077)) | ||||||
|  | - Fix: frontend tasks display in 1.10.0 [@shamoon](https://github.com/shamoon) ([#2073](https://github.com/paperless-ngx/paperless-ngx/pull/2073)) | ||||||
|  | - Bugfix: Don't silence an exception when trying to handle file naming [@stumpylog](https://github.com/stumpylog) ([#2062](https://github.com/paperless-ngx/paperless-ngx/pull/2062)) | ||||||
|  | - Bugfix: Some tesseract languages aren't detected as installed. [@stumpylog](https://github.com/stumpylog) ([#2057](https://github.com/paperless-ngx/paperless-ngx/pull/2057)) | ||||||
|  | 
 | ||||||
|  | ## paperless-ngx 1.10.0 | ||||||
|  | 
 | ||||||
|  | ### Features | ||||||
|  | 
 | ||||||
|  | - Feature: Capture stdout \& stderr of the pre/post consume scripts [@stumpylog](https://github.com/stumpylog) ([#1967](https://github.com/paperless-ngx/paperless-ngx/pull/1967)) | ||||||
|  | - Feature: Allow running custom container initialization scripts [@stumpylog](https://github.com/stumpylog) ([#1838](https://github.com/paperless-ngx/paperless-ngx/pull/1838)) | ||||||
|  | - Feature: Add more file name formatting options [@stumpylog](https://github.com/stumpylog) ([#1906](https://github.com/paperless-ngx/paperless-ngx/pull/1906)) | ||||||
|  | - Feature: 1.9.2 UI tweaks [@shamoon](https://github.com/shamoon) ([#1886](https://github.com/paperless-ngx/paperless-ngx/pull/1886)) | ||||||
|  | - Feature: Optional celery monitoring with Flower [@stumpylog](https://github.com/stumpylog) ([#1810](https://github.com/paperless-ngx/paperless-ngx/pull/1810)) | ||||||
|  | - Feature: Save pending tasks for frontend [@stumpylog](https://github.com/stumpylog) ([#1816](https://github.com/paperless-ngx/paperless-ngx/pull/1816)) | ||||||
|  | - Feature: Improved processing for automatic matching [@stumpylog](https://github.com/stumpylog) ([#1609](https://github.com/paperless-ngx/paperless-ngx/pull/1609)) | ||||||
|  | - Feature: Transition to celery for background tasks [@stumpylog](https://github.com/stumpylog) ([#1648](https://github.com/paperless-ngx/paperless-ngx/pull/1648)) | ||||||
|  | - Feature: UI Welcome Tour [@shamoon](https://github.com/shamoon) ([#1644](https://github.com/paperless-ngx/paperless-ngx/pull/1644)) | ||||||
|  | - Feature: slim sidebar [@shamoon](https://github.com/shamoon) ([#1641](https://github.com/paperless-ngx/paperless-ngx/pull/1641)) | ||||||
|  | - change default matching algo to auto and move to constant [@NiFNi](https://github.com/NiFNi) ([#1754](https://github.com/paperless-ngx/paperless-ngx/pull/1754)) | ||||||
|  | - Feature: Enable end to end Tika testing in CI [@stumpylog](https://github.com/stumpylog) ([#1757](https://github.com/paperless-ngx/paperless-ngx/pull/1757)) | ||||||
|  | - Feature: frontend update checking settings [@shamoon](https://github.com/shamoon) ([#1692](https://github.com/paperless-ngx/paperless-ngx/pull/1692)) | ||||||
|  | - Feature: Upgrade to qpdf 11, pikepdf 6 \& ocrmypdf 14 [@stumpylog](https://github.com/stumpylog) ([#1642](https://github.com/paperless-ngx/paperless-ngx/pull/1642)) | ||||||
|  | 
 | ||||||
|  | ### Bug Fixes | ||||||
|  | 
 | ||||||
|  | - Bugfix: Fix created_date being a string [@stumpylog](https://github.com/stumpylog) ([#2023](https://github.com/paperless-ngx/paperless-ngx/pull/2023)) | ||||||
|  | - Bugfix: Fixes an issue with mixed text and images when redoing OCR [@stumpylog](https://github.com/stumpylog) ([#2017](https://github.com/paperless-ngx/paperless-ngx/pull/2017)) | ||||||
|  | - Bugfix: Always re-try barcodes with pdf2image [@stumpylog](https://github.com/stumpylog) ([#1953](https://github.com/paperless-ngx/paperless-ngx/pull/1953)) | ||||||
|  | - Fix: using `CONSUMER_SUBDIRS_AS_TAGS` causes failure with Celery in `dev` [@shamoon](https://github.com/shamoon) ([#1942](https://github.com/paperless-ngx/paperless-ngx/pull/1942)) | ||||||
|  | - Fix mail consumption broken in `dev` after move to celery [@shamoon](https://github.com/shamoon) ([#1934](https://github.com/paperless-ngx/paperless-ngx/pull/1934)) | ||||||
|  | - Bugfix: Prevent file handling from running with stale data [@stumpylog](https://github.com/stumpylog) ([#1905](https://github.com/paperless-ngx/paperless-ngx/pull/1905)) | ||||||
|  | - Chore: Reduce nuisance CI test failures [@stumpylog](https://github.com/stumpylog) ([#1922](https://github.com/paperless-ngx/paperless-ngx/pull/1922)) | ||||||
|  | - Bugfix: Unintentional deletion of feature tagged Docker images [@stumpylog](https://github.com/stumpylog) ([#1896](https://github.com/paperless-ngx/paperless-ngx/pull/1896)) | ||||||
|  | - Fix: independent control of saved views [@shamoon](https://github.com/shamoon) ([#1868](https://github.com/paperless-ngx/paperless-ngx/pull/1868)) | ||||||
|  | - Fix: frontend relative date searches [@shamoon](https://github.com/shamoon) ([#1865](https://github.com/paperless-ngx/paperless-ngx/pull/1865)) | ||||||
|  | - Chore: Fixes pipenv issues [@stumpylog](https://github.com/stumpylog) ([#1873](https://github.com/paperless-ngx/paperless-ngx/pull/1873)) | ||||||
|  | - Bugfix: Handle password protected PDFs during barcode detection [@stumpylog](https://github.com/stumpylog) ([#1858](https://github.com/paperless-ngx/paperless-ngx/pull/1858)) | ||||||
|  | - Fix: Allows configuring barcodes with pdf2image instead of pikepdf [@stumpylog](https://github.com/stumpylog) ([#1857](https://github.com/paperless-ngx/paperless-ngx/pull/1857)) | ||||||
|  | - Bugfix: Reverts the change around skip_noarchive [@stumpylog](https://github.com/stumpylog) ([#1829](https://github.com/paperless-ngx/paperless-ngx/pull/1829)) | ||||||
|  | - Fix: missing loadViewConfig breaks loading saved view [@shamoon](https://github.com/shamoon) ([#1792](https://github.com/paperless-ngx/paperless-ngx/pull/1792)) | ||||||
|  | - Bugfix: Fallback to pdf2image if pikepdf fails [@stumpylog](https://github.com/stumpylog) ([#1745](https://github.com/paperless-ngx/paperless-ngx/pull/1745)) | ||||||
|  | - Fix: creating new storage path on document edit fails to update menu [@shamoon](https://github.com/shamoon) ([#1777](https://github.com/paperless-ngx/paperless-ngx/pull/1777)) | ||||||
|  | - Bugfix: Files containing barcodes uploaded via web are not consumed after splitting [@stumpylog](https://github.com/stumpylog) ([#1762](https://github.com/paperless-ngx/paperless-ngx/pull/1762)) | ||||||
|  | - Bugfix: Fix email labeling for non-Gmail servers [@stumpylog](https://github.com/stumpylog) ([#1755](https://github.com/paperless-ngx/paperless-ngx/pull/1755)) | ||||||
|  | - Fix: allow preview for .csv files [@shamoon](https://github.com/shamoon) ([#1744](https://github.com/paperless-ngx/paperless-ngx/pull/1744)) | ||||||
|  | - Bugfix: csv recognition by consumer [@bin101](https://github.com/bin101) ([#1726](https://github.com/paperless-ngx/paperless-ngx/pull/1726)) | ||||||
|  | - Bugfix: Include document title when a duplicate is detected [@stumpylog](https://github.com/stumpylog) ([#1696](https://github.com/paperless-ngx/paperless-ngx/pull/1696)) | ||||||
|  | - Bugfix: Set MySql charset [@stumpylog](https://github.com/stumpylog) ([#1687](https://github.com/paperless-ngx/paperless-ngx/pull/1687)) | ||||||
|  | - Mariadb compose files should use `PAPERLESS_DBPASS` [@shamoon](https://github.com/shamoon) ([#1683](https://github.com/paperless-ngx/paperless-ngx/pull/1683)) | ||||||
|  | 
 | ||||||
|  | ### Documentation | ||||||
|  | 
 | ||||||
|  | - Documentation: Update MariaDB docs to note some potential issues [@stumpylog](https://github.com/stumpylog) ([#2016](https://github.com/paperless-ngx/paperless-ngx/pull/2016)) | ||||||
|  | - Documentation: Add note re MS exchange servers [@shamoon](https://github.com/shamoon) ([#1780](https://github.com/paperless-ngx/paperless-ngx/pull/1780)) | ||||||
|  | - Chore: Updates Gotenberg versions [@stumpylog](https://github.com/stumpylog) ([#1768](https://github.com/paperless-ngx/paperless-ngx/pull/1768)) | ||||||
|  | - Documentation: Tweak LinuxServer [@stumpylog](https://github.com/stumpylog) ([#1761](https://github.com/paperless-ngx/paperless-ngx/pull/1761)) | ||||||
|  | - Documentation: Adds troubleshooting note about Kubernetes and ports [@stumpylog](https://github.com/stumpylog) ([#1731](https://github.com/paperless-ngx/paperless-ngx/pull/1731)) | ||||||
|  | - Documentation: LinuxServer.io Migration [@stumpylog](https://github.com/stumpylog) ([#1733](https://github.com/paperless-ngx/paperless-ngx/pull/1733)) | ||||||
|  | - [Documentation] Add v1.9.2 changelog [@github-actions](https://github.com/github-actions) ([#1671](https://github.com/paperless-ngx/paperless-ngx/pull/1671)) | ||||||
|  | 
 | ||||||
|  | ### Maintenance | ||||||
|  | 
 | ||||||
|  | - Bump tj-actions/changed-files from 32 to 34 [@dependabot](https://github.com/dependabot) ([#1915](https://github.com/paperless-ngx/paperless-ngx/pull/1915)) | ||||||
|  | - Chore: Fix `dev` trying to build Pillow or lxml [@stumpylog](https://github.com/stumpylog) ([#1909](https://github.com/paperless-ngx/paperless-ngx/pull/1909)) | ||||||
|  | - Chore: Fixes pipenv issues [@stumpylog](https://github.com/stumpylog) ([#1873](https://github.com/paperless-ngx/paperless-ngx/pull/1873)) | ||||||
|  | - Chore: Simplified registry cleanup [@stumpylog](https://github.com/stumpylog) ([#1812](https://github.com/paperless-ngx/paperless-ngx/pull/1812)) | ||||||
|  | - Chore: Fixing deprecated workflow commands [@stumpylog](https://github.com/stumpylog) ([#1786](https://github.com/paperless-ngx/paperless-ngx/pull/1786)) | ||||||
|  | - Chore: Python library update + test fixes [@stumpylog](https://github.com/stumpylog) ([#1773](https://github.com/paperless-ngx/paperless-ngx/pull/1773)) | ||||||
|  | - Chore: Updates Gotenberg versions [@stumpylog](https://github.com/stumpylog) ([#1768](https://github.com/paperless-ngx/paperless-ngx/pull/1768)) | ||||||
|  | - Bump leonsteinhaeuser/project-beta-automations from 1.3.0 to 2.0.1 [@dependabot](https://github.com/dependabot) ([#1703](https://github.com/paperless-ngx/paperless-ngx/pull/1703)) | ||||||
|  | - Bump tj-actions/changed-files from 29.0.2 to 31.0.2 [@dependabot](https://github.com/dependabot) ([#1702](https://github.com/paperless-ngx/paperless-ngx/pull/1702)) | ||||||
|  | - Bump actions/checkout from 2 to 3 [@dependabot](https://github.com/dependabot) ([#1704](https://github.com/paperless-ngx/paperless-ngx/pull/1704)) | ||||||
|  | - Bump actions/setup-python from 3 to 4 [@dependabot](https://github.com/dependabot) ([#1705](https://github.com/paperless-ngx/paperless-ngx/pull/1705)) | ||||||
|  | 
 | ||||||
|  | ### Dependencies | ||||||
|  | 
 | ||||||
|  | <details> | ||||||
|  | <summary>31 changes</summary> | ||||||
|  | 
 | ||||||
|  | - Bugfix: Downgrade cryptography for armv7 compatibility [@stumpylog](https://github.com/stumpylog) ([#1954](https://github.com/paperless-ngx/paperless-ngx/pull/1954)) | ||||||
|  | - Chore: Bulk library updates + loosen restrictions [@stumpylog](https://github.com/stumpylog) ([#1949](https://github.com/paperless-ngx/paperless-ngx/pull/1949)) | ||||||
|  | - Bump tj-actions/changed-files from 32 to 34 [@dependabot](https://github.com/dependabot) ([#1915](https://github.com/paperless-ngx/paperless-ngx/pull/1915)) | ||||||
|  | - Bump scikit-learn from 1.1.2 to 1.1.3 [@dependabot](https://github.com/dependabot) ([#1903](https://github.com/paperless-ngx/paperless-ngx/pull/1903)) | ||||||
|  | - Bump angular packages as bundle [@dependabot](https://github.com/dependabot) ([#1910](https://github.com/paperless-ngx/paperless-ngx/pull/1910)) | ||||||
|  | - Bump ngx-ui-tour-ng-bootstrap from 11.0.0 to 11.1.0 in /src-ui [@dependabot](https://github.com/dependabot) ([#1911](https://github.com/paperless-ngx/paperless-ngx/pull/1911)) | ||||||
|  | - Bump jest-environment-jsdom from 29.1.2 to 29.2.2 in /src-ui [@dependabot](https://github.com/dependabot) ([#1914](https://github.com/paperless-ngx/paperless-ngx/pull/1914)) | ||||||
|  | - Bump pillow from 9.2.0 to 9.3.0 [@dependabot](https://github.com/dependabot) ([#1904](https://github.com/paperless-ngx/paperless-ngx/pull/1904)) | ||||||
|  | - Bump pytest from 7.1.3 to 7.2.0 [@dependabot](https://github.com/dependabot) ([#1902](https://github.com/paperless-ngx/paperless-ngx/pull/1902)) | ||||||
|  | - Bump tox from 3.26.0 to 3.27.0 [@dependabot](https://github.com/dependabot) ([#1901](https://github.com/paperless-ngx/paperless-ngx/pull/1901)) | ||||||
|  | - Bump zipp from 3.9.0 to 3.10.0 [@dependabot](https://github.com/dependabot) ([#1860](https://github.com/paperless-ngx/paperless-ngx/pull/1860)) | ||||||
|  | - Bump pytest-env from 0.6.2 to 0.8.1 [@dependabot](https://github.com/dependabot) ([#1859](https://github.com/paperless-ngx/paperless-ngx/pull/1859)) | ||||||
|  | - Bump sphinx from 5.2.3 to 5.3.0 [@dependabot](https://github.com/dependabot) ([#1817](https://github.com/paperless-ngx/paperless-ngx/pull/1817)) | ||||||
|  | - Chore: downgrade channels-redis [@stumpylog](https://github.com/stumpylog) ([#1802](https://github.com/paperless-ngx/paperless-ngx/pull/1802)) | ||||||
|  | - Chore: Update to qpdf 11.1.1 and update backend libraries [@stumpylog](https://github.com/stumpylog) ([#1749](https://github.com/paperless-ngx/paperless-ngx/pull/1749)) | ||||||
|  | - Bump myst-parser from 0.18.0 to 0.18.1 [@dependabot](https://github.com/dependabot) ([#1738](https://github.com/paperless-ngx/paperless-ngx/pull/1738)) | ||||||
|  | - Bump leonsteinhaeuser/project-beta-automations from 1.3.0 to 2.0.1 [@dependabot](https://github.com/dependabot) ([#1703](https://github.com/paperless-ngx/paperless-ngx/pull/1703)) | ||||||
|  | - Bump tj-actions/changed-files from 29.0.2 to 31.0.2 [@dependabot](https://github.com/dependabot) ([#1702](https://github.com/paperless-ngx/paperless-ngx/pull/1702)) | ||||||
|  | - Bump actions/checkout from 2 to 3 [@dependabot](https://github.com/dependabot) ([#1704](https://github.com/paperless-ngx/paperless-ngx/pull/1704)) | ||||||
|  | - Bump actions/setup-python from 3 to 4 [@dependabot](https://github.com/dependabot) ([#1705](https://github.com/paperless-ngx/paperless-ngx/pull/1705)) | ||||||
|  | - Bump rxjs from 7.5.6 to 7.5.7 in /src-ui [@dependabot](https://github.com/dependabot) ([#1720](https://github.com/paperless-ngx/paperless-ngx/pull/1720)) | ||||||
|  | - Bump uuid from 8.3.2 to 9.0.0 in /src-ui [@dependabot](https://github.com/dependabot) ([#1716](https://github.com/paperless-ngx/paperless-ngx/pull/1716)) | ||||||
|  | - Bump ng2-pdf-viewer from 9.1.0 to 9.1.2 in /src-ui [@dependabot](https://github.com/dependabot) ([#1717](https://github.com/paperless-ngx/paperless-ngx/pull/1717)) | ||||||
|  | - Bump ngx-color from 8.0.2 to 8.0.3 in /src-ui [@dependabot](https://github.com/dependabot) ([#1715](https://github.com/paperless-ngx/paperless-ngx/pull/1715)) | ||||||
|  | - Bump concurrently from 7.3.0 to 7.4.0 in /src-ui [@dependabot](https://github.com/dependabot) ([#1719](https://github.com/paperless-ngx/paperless-ngx/pull/1719)) | ||||||
|  | - Bump [@<!---->types/node from 18.7.14 to 18.7.23 in /src-ui @dependabot](https://github.com/<!---->types/node from 18.7.14 to 18.7.23 in /src-ui @dependabot) ([#1718](https://github.com/paperless-ngx/paperless-ngx/pull/1718)) | ||||||
|  | - Bump jest-environment-jsdom from 29.0.1 to 29.1.2 in /src-ui [@dependabot](https://github.com/dependabot) ([#1714](https://github.com/paperless-ngx/paperless-ngx/pull/1714)) | ||||||
|  | - Bump [@<!---->angular/cli @<!---->angular/core @dependabot](https://github.com/<!---->angular/cli @<!---->angular/core @dependabot) ([#1708](https://github.com/paperless-ngx/paperless-ngx/pull/1708)) | ||||||
|  | - Bump cypress from 10.7.0 to 10.9.0 in /src-ui [@dependabot](https://github.com/dependabot) ([#1707](https://github.com/paperless-ngx/paperless-ngx/pull/1707)) | ||||||
|  | - Bump bootstrap from 5.2.0 to 5.2.1 in /src-ui [@dependabot](https://github.com/dependabot) ([#1710](https://github.com/paperless-ngx/paperless-ngx/pull/1710)) | ||||||
|  | - Bump typescript from 4.7.4 to 4.8.4 in /src-ui [@dependabot](https://github.com/dependabot) ([#1706](https://github.com/paperless-ngx/paperless-ngx/pull/1706)) | ||||||
|  | </details> | ||||||
|  | 
 | ||||||
|  | ### All App Changes | ||||||
|  | 
 | ||||||
|  | - Add info that re-do OCR doesnt automatically refresh content [@shamoon](https://github.com/shamoon) ([#2025](https://github.com/paperless-ngx/paperless-ngx/pull/2025)) | ||||||
|  | - Bugfix: Fix created_date being a string [@stumpylog](https://github.com/stumpylog) ([#2023](https://github.com/paperless-ngx/paperless-ngx/pull/2023)) | ||||||
|  | - Bugfix: Fixes an issue with mixed text and images when redoing OCR [@stumpylog](https://github.com/stumpylog) ([#2017](https://github.com/paperless-ngx/paperless-ngx/pull/2017)) | ||||||
|  | - Bugfix: Don't allow exceptions during date parsing to fail consume [@stumpylog](https://github.com/stumpylog) ([#1998](https://github.com/paperless-ngx/paperless-ngx/pull/1998)) | ||||||
|  | - Feature: Capture stdout \& stderr of the pre/post consume scripts [@stumpylog](https://github.com/stumpylog) ([#1967](https://github.com/paperless-ngx/paperless-ngx/pull/1967)) | ||||||
|  | - Bugfix: Always re-try barcodes with pdf2image [@stumpylog](https://github.com/stumpylog) ([#1953](https://github.com/paperless-ngx/paperless-ngx/pull/1953)) | ||||||
|  | - Fix: using `CONSUMER_SUBDIRS_AS_TAGS` causes failure with Celery in `dev` [@shamoon](https://github.com/shamoon) ([#1942](https://github.com/paperless-ngx/paperless-ngx/pull/1942)) | ||||||
|  | - Fix mail consumption broken in `dev` after move to celery [@shamoon](https://github.com/shamoon) ([#1934](https://github.com/paperless-ngx/paperless-ngx/pull/1934)) | ||||||
|  | - Bugfix: Prevent file handling from running with stale data [@stumpylog](https://github.com/stumpylog) ([#1905](https://github.com/paperless-ngx/paperless-ngx/pull/1905)) | ||||||
|  | - Chore: Reduce nuisance CI test failures [@stumpylog](https://github.com/stumpylog) ([#1922](https://github.com/paperless-ngx/paperless-ngx/pull/1922)) | ||||||
|  | - Bump scikit-learn from 1.1.2 to 1.1.3 [@dependabot](https://github.com/dependabot) ([#1903](https://github.com/paperless-ngx/paperless-ngx/pull/1903)) | ||||||
|  | - Bump angular packages as bundle [@dependabot](https://github.com/dependabot) ([#1910](https://github.com/paperless-ngx/paperless-ngx/pull/1910)) | ||||||
|  | - Bump ngx-ui-tour-ng-bootstrap from 11.0.0 to 11.1.0 in /src-ui [@dependabot](https://github.com/dependabot) ([#1911](https://github.com/paperless-ngx/paperless-ngx/pull/1911)) | ||||||
|  | - Bump jest-environment-jsdom from 29.1.2 to 29.2.2 in /src-ui [@dependabot](https://github.com/dependabot) ([#1914](https://github.com/paperless-ngx/paperless-ngx/pull/1914)) | ||||||
|  | - Feature: Add more file name formatting options [@stumpylog](https://github.com/stumpylog) ([#1906](https://github.com/paperless-ngx/paperless-ngx/pull/1906)) | ||||||
|  | - Bump pillow from 9.2.0 to 9.3.0 [@dependabot](https://github.com/dependabot) ([#1904](https://github.com/paperless-ngx/paperless-ngx/pull/1904)) | ||||||
|  | - Bump pytest from 7.1.3 to 7.2.0 [@dependabot](https://github.com/dependabot) ([#1902](https://github.com/paperless-ngx/paperless-ngx/pull/1902)) | ||||||
|  | - Bump tox from 3.26.0 to 3.27.0 [@dependabot](https://github.com/dependabot) ([#1901](https://github.com/paperless-ngx/paperless-ngx/pull/1901)) | ||||||
|  | - directly use rapidfuzz [@maxbachmann](https://github.com/maxbachmann) ([#1899](https://github.com/paperless-ngx/paperless-ngx/pull/1899)) | ||||||
|  | - Feature: 1.9.2 UI tweaks [@shamoon](https://github.com/shamoon) ([#1886](https://github.com/paperless-ngx/paperless-ngx/pull/1886)) | ||||||
|  | - Bump zipp from 3.9.0 to 3.10.0 [@dependabot](https://github.com/dependabot) ([#1860](https://github.com/paperless-ngx/paperless-ngx/pull/1860)) | ||||||
|  | - Fix: independent control of saved views [@shamoon](https://github.com/shamoon) ([#1868](https://github.com/paperless-ngx/paperless-ngx/pull/1868)) | ||||||
|  | - Fix: frontend relative date searches [@shamoon](https://github.com/shamoon) ([#1865](https://github.com/paperless-ngx/paperless-ngx/pull/1865)) | ||||||
|  | - Django error W003 - MariaDB may not allow unique CharFields to have a max_length > 255. [@Sblop](https://github.com/Sblop) ([#1881](https://github.com/paperless-ngx/paperless-ngx/pull/1881)) | ||||||
|  | - Bump pytest-env from 0.6.2 to 0.8.1 [@dependabot](https://github.com/dependabot) ([#1859](https://github.com/paperless-ngx/paperless-ngx/pull/1859)) | ||||||
|  | - Fix: Allows configuring barcodes with pdf2image instead of pikepdf [@stumpylog](https://github.com/stumpylog) ([#1857](https://github.com/paperless-ngx/paperless-ngx/pull/1857)) | ||||||
|  | - Feature: Save pending tasks for frontend [@stumpylog](https://github.com/stumpylog) ([#1816](https://github.com/paperless-ngx/paperless-ngx/pull/1816)) | ||||||
|  | - Bugfix: Reverts the change around skip_noarchive [@stumpylog](https://github.com/stumpylog) ([#1829](https://github.com/paperless-ngx/paperless-ngx/pull/1829)) | ||||||
|  | - Bump sphinx from 5.2.3 to 5.3.0 [@dependabot](https://github.com/dependabot) ([#1817](https://github.com/paperless-ngx/paperless-ngx/pull/1817)) | ||||||
|  | - Fix: missing loadViewConfig breaks loading saved view [@shamoon](https://github.com/shamoon) ([#1792](https://github.com/paperless-ngx/paperless-ngx/pull/1792)) | ||||||
|  | - Bugfix: Fallback to pdf2image if pikepdf fails [@stumpylog](https://github.com/stumpylog) ([#1745](https://github.com/paperless-ngx/paperless-ngx/pull/1745)) | ||||||
|  | - Fix: creating new storage path on document edit fails to update menu [@shamoon](https://github.com/shamoon) ([#1777](https://github.com/paperless-ngx/paperless-ngx/pull/1777)) | ||||||
|  | - Chore: Python library update + test fixes [@stumpylog](https://github.com/stumpylog) ([#1773](https://github.com/paperless-ngx/paperless-ngx/pull/1773)) | ||||||
|  | - Feature: Improved processing for automatic matching [@stumpylog](https://github.com/stumpylog) ([#1609](https://github.com/paperless-ngx/paperless-ngx/pull/1609)) | ||||||
|  | - Feature: Transition to celery for background tasks [@stumpylog](https://github.com/stumpylog) ([#1648](https://github.com/paperless-ngx/paperless-ngx/pull/1648)) | ||||||
|  | - Feature: UI Welcome Tour [@shamoon](https://github.com/shamoon) ([#1644](https://github.com/paperless-ngx/paperless-ngx/pull/1644)) | ||||||
|  | - Feature: slim sidebar [@shamoon](https://github.com/shamoon) ([#1641](https://github.com/paperless-ngx/paperless-ngx/pull/1641)) | ||||||
|  | - Bugfix: Files containing barcodes uploaded via web are not consumed after splitting [@stumpylog](https://github.com/stumpylog) ([#1762](https://github.com/paperless-ngx/paperless-ngx/pull/1762)) | ||||||
|  | - change default matching algo to auto and move to constant [@NiFNi](https://github.com/NiFNi) ([#1754](https://github.com/paperless-ngx/paperless-ngx/pull/1754)) | ||||||
|  | - Bugfix: Fix email labeling for non-Gmail servers [@stumpylog](https://github.com/stumpylog) ([#1755](https://github.com/paperless-ngx/paperless-ngx/pull/1755)) | ||||||
|  | - Feature: frontend update checking settings [@shamoon](https://github.com/shamoon) ([#1692](https://github.com/paperless-ngx/paperless-ngx/pull/1692)) | ||||||
|  | - Fix: allow preview for .csv files [@shamoon](https://github.com/shamoon) ([#1744](https://github.com/paperless-ngx/paperless-ngx/pull/1744)) | ||||||
|  | - Bump myst-parser from 0.18.0 to 0.18.1 [@dependabot](https://github.com/dependabot) ([#1738](https://github.com/paperless-ngx/paperless-ngx/pull/1738)) | ||||||
|  | - Bugfix: csv recognition by consumer [@bin101](https://github.com/bin101) ([#1726](https://github.com/paperless-ngx/paperless-ngx/pull/1726)) | ||||||
|  | - Bugfix: Include document title when a duplicate is detected [@stumpylog](https://github.com/stumpylog) ([#1696](https://github.com/paperless-ngx/paperless-ngx/pull/1696)) | ||||||
|  | - Bump rxjs from 7.5.6 to 7.5.7 in /src-ui [@dependabot](https://github.com/dependabot) ([#1720](https://github.com/paperless-ngx/paperless-ngx/pull/1720)) | ||||||
|  | - Bump uuid from 8.3.2 to 9.0.0 in /src-ui [@dependabot](https://github.com/dependabot) ([#1716](https://github.com/paperless-ngx/paperless-ngx/pull/1716)) | ||||||
|  | - Bump ng2-pdf-viewer from 9.1.0 to 9.1.2 in /src-ui [@dependabot](https://github.com/dependabot) ([#1717](https://github.com/paperless-ngx/paperless-ngx/pull/1717)) | ||||||
|  | - Bump ngx-color from 8.0.2 to 8.0.3 in /src-ui [@dependabot](https://github.com/dependabot) ([#1715](https://github.com/paperless-ngx/paperless-ngx/pull/1715)) | ||||||
|  | - Bump concurrently from 7.3.0 to 7.4.0 in /src-ui [@dependabot](https://github.com/dependabot) ([#1719](https://github.com/paperless-ngx/paperless-ngx/pull/1719)) | ||||||
|  | - Bump [@<!---->types/node from 18.7.14 to 18.7.23 in /src-ui @dependabot](https://github.com/<!---->types/node from 18.7.14 to 18.7.23 in /src-ui @dependabot) ([#1718](https://github.com/paperless-ngx/paperless-ngx/pull/1718)) | ||||||
|  | - Bump jest-environment-jsdom from 29.0.1 to 29.1.2 in /src-ui [@dependabot](https://github.com/dependabot) ([#1714](https://github.com/paperless-ngx/paperless-ngx/pull/1714)) | ||||||
|  | - Bump [@<!---->angular/cli @<!---->angular/core @dependabot](https://github.com/<!---->angular/cli @<!---->angular/core @dependabot) ([#1708](https://github.com/paperless-ngx/paperless-ngx/pull/1708)) | ||||||
|  | - Bump cypress from 10.7.0 to 10.9.0 in /src-ui [@dependabot](https://github.com/dependabot) ([#1707](https://github.com/paperless-ngx/paperless-ngx/pull/1707)) | ||||||
|  | - Bump bootstrap from 5.2.0 to 5.2.1 in /src-ui [@dependabot](https://github.com/dependabot) ([#1710](https://github.com/paperless-ngx/paperless-ngx/pull/1710)) | ||||||
|  | - Bump typescript from 4.7.4 to 4.8.4 in /src-ui [@dependabot](https://github.com/dependabot) ([#1706](https://github.com/paperless-ngx/paperless-ngx/pull/1706)) | ||||||
|  | - Bugfix: Set MySql charset [@stumpylog](https://github.com/stumpylog) ([#1687](https://github.com/paperless-ngx/paperless-ngx/pull/1687)) | ||||||
|  | 
 | ||||||
|  | ## paperless-ngx 1.9.2 | ||||||
|  | 
 | ||||||
|  | ### Bug Fixes | ||||||
|  | 
 | ||||||
|  | - Bugfix: Allow PAPERLESS_OCR_CLEAN=none [@shamoon](https://github.com/shamoon) ([#1670](https://github.com/paperless-ngx/paperless-ngx/pull/1670)) | ||||||
|  | 
 | ||||||
|  | ### All App Changes | ||||||
|  | 
 | ||||||
|  | - Chore: Bumps version numbers to 1.9.2 [@stumpylog](https://github.com/stumpylog) ([#1666](https://github.com/paperless-ngx/paperless-ngx/pull/1666)) | ||||||
|  | 
 | ||||||
| ## paperless-ngx 1.9.1 | ## paperless-ngx 1.9.1 | ||||||
| 
 | 
 | ||||||
|  | ### Notes | ||||||
|  | 
 | ||||||
|  | - Version 1.9.1 incorrectly displays the version string as 1.9.0 | ||||||
|  | 
 | ||||||
| ### Bug Fixes | ### Bug Fixes | ||||||
| 
 | 
 | ||||||
| - Bugfix: Fixes missing OCR mode skip_noarchive [@stumpylog](https://github.com/stumpylog) ([#1645](https://github.com/paperless-ngx/paperless-ngx/pull/1645)) | - Bugfix: Fixes missing OCR mode skip_noarchive [@stumpylog](https://github.com/stumpylog) ([#1645](https://github.com/paperless-ngx/paperless-ngx/pull/1645)) | ||||||
| @ -395,7 +618,7 @@ | |||||||
| 
 | 
 | ||||||
| - Allow setting more than one tag in mail rules | - Allow setting more than one tag in mail rules | ||||||
|   [\@jonasc](https://github.com/jonasc) ([\#270](https://github.com/paperless-ngx/paperless-ngx/pull/270)) |   [\@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)) |   ([\#283](https://github.com/paperless-ngx/paperless-ngx/pull/283)) | ||||||
| - Fix: download buttons should disable while waiting | - Fix: download buttons should disable while waiting | ||||||
|   [\@shamoon](https://github.com/shamoon) ([\#630](https://github.com/paperless-ngx/paperless-ngx/pull/630)) |   [\@shamoon](https://github.com/shamoon) ([\#630](https://github.com/paperless-ngx/paperless-ngx/pull/630)) | ||||||
| @ -425,7 +648,7 @@ | |||||||
| 
 | 
 | ||||||
| ### Bug Fixes | ### 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)) |   [\@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)) | - Fix: scanners table [\@qcasey](https://github.com/qcasey) ([\#690](https://github.com/paperless-ngx/paperless-ngx/pull/690)) | ||||||
| - Adds wait for file before consuming | - Adds wait for file before consuming | ||||||
| @ -462,7 +685,7 @@ | |||||||
|   ([\#393](https://github.com/paperless-ngx/paperless-ngx/pull/393)) |   ([\#393](https://github.com/paperless-ngx/paperless-ngx/pull/393)) | ||||||
| - Fix filterable dropdown buttons arent translated | - Fix filterable dropdown buttons arent translated | ||||||
|   [\@shamoon](https://github.com/shamoon) ([\#366](https://github.com/paperless-ngx/paperless-ngx/pull/366)) |   [\@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)) |   [\@a17t](https://github.com/a17t) ([\#246](https://github.com/paperless-ngx/paperless-ngx/pull/246)) | ||||||
| - Fix minor sphinx errors [\@shamoon](https://github.com/shamoon) | - Fix minor sphinx errors [\@shamoon](https://github.com/shamoon) | ||||||
|   ([\#322](https://github.com/paperless-ngx/paperless-ngx/pull/322)) |   ([\#322](https://github.com/paperless-ngx/paperless-ngx/pull/322)) | ||||||
| @ -524,7 +747,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 | you to everyone on the paperless-ngx team for your initiative and | ||||||
| excellent teamwork! | 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 | includes new feature updates and bug fixes. Major backend and UI changes | ||||||
| include: | include: | ||||||
| 
 | 
 | ||||||
| @ -544,14 +767,14 @@ include: | |||||||
|   when document list is reloading ([jonaswinkler\#1297](https://github.com/jonaswinkler/paperless-ng/pull/1297)). |   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 | - [\@shamoon](https://github.com/shamoon) improved the PDF viewer on | ||||||
|   mobile ([\#2](https://github.com/paperless-ngx/paperless-ngx/pull/2)). |   mobile ([\#2](https://github.com/paperless-ngx/paperless-ngx/pull/2)). | ||||||
| - [\@shamoon](https://github.com/shamoon) added \'any\' / \'all\' and | - [\@shamoon](https://github.com/shamoon) added 'any' / 'all' and | ||||||
|   \'not\' filtering with tags ([\#10](https://github.com/paperless-ngx/paperless-ngx/pull/10)). |   'not' filtering with tags ([\#10](https://github.com/paperless-ngx/paperless-ngx/pull/10)). | ||||||
| - [\@shamoon](https://github.com/shamoon) added warnings for unsaved | - [\@shamoon](https://github.com/shamoon) added warnings for unsaved | ||||||
|   changes, with smart edit buttons ([\#13](https://github.com/paperless-ngx/paperless-ngx/pull/13)). |   changes, with smart edit buttons ([\#13](https://github.com/paperless-ngx/paperless-ngx/pull/13)). | ||||||
| - [\@benjaminfrank](https://github.com/benjaminfrank) enabled a | - [\@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)). |   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 | - [\@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`. |   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 | - [\@amenk](https://github.com/amenk) fixed the search box overlay | ||||||
|   menu on mobile ([\#32](https://github.com/paperless-ngx/paperless-ngx/pull/32)). |   menu on mobile ([\#32](https://github.com/paperless-ngx/paperless-ngx/pull/32)). | ||||||
| - [\@dblitt](https://github.com/dblitt) updated the login form to not | - [\@dblitt](https://github.com/dblitt) updated the login form to not | ||||||
| @ -727,26 +950,22 @@ This is a maintenance release. | |||||||
| - Changes | - Changes | ||||||
|   - Firefox only: Highlight search query in PDF previews. |   - Firefox only: Highlight search query in PDF previews. | ||||||
|   - New URL pattern for accessing documents by ASN directly |   - 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. |   - Added logging when executing pre\* and post-consume scripts. | ||||||
|   - Better error logging during document consumption. |   - Better error logging during document consumption. | ||||||
|   - Updated python dependencies. |   - 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. |     dialogs on the document details page. | ||||||
| - Fixes | - Fixes | ||||||
|   - Fixed an issue with null characters in the document content. |   - Fixed an issue with null characters in the document content. | ||||||
| 
 | 
 | ||||||
| ::: {.note} | !!! note | ||||||
| ::: {.title} |  | ||||||
| Note |  | ||||||
| ::: |  | ||||||
| 
 | 
 | ||||||
| The changed to the full text searching require you to reindex your | 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` | do anything._ To do this, execute the `document_index reindex` | ||||||
| management command (see `administration-index`{.interpreted-text | management command (see `administration-index`{.interpreted-text | ||||||
| role="ref"}). | role="ref"}). | ||||||
| ::: |  | ||||||
| 
 | 
 | ||||||
| ### paperless-ng 1.3.2 | ### paperless-ng 1.3.2 | ||||||
| 
 | 
 | ||||||
| @ -849,7 +1068,7 @@ This release contains new database migrations. | |||||||
|   worker processes of the web server. See |   worker processes of the web server. See | ||||||
|   `configuration-docker`{.interpreted-text role="ref"}. |   `configuration-docker`{.interpreted-text role="ref"}. | ||||||
| - Some more memory usage optimizations. | - 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 | ### paperless-ng 1.1.2 | ||||||
| 
 | 
 | ||||||
| @ -869,8 +1088,8 @@ This release contains new database migrations. | |||||||
| 
 | 
 | ||||||
| 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 | - Fixed a bug in the sanity checker that would cause it to display "x | ||||||
|   not in list\" errors instead of actual issues. |   not in list" errors instead of actual issues. | ||||||
| - Fixed a bug with filename generation for archive filenames that | - Fixed a bug with filename generation for archive filenames that | ||||||
|   would cause the archive files of two documents to overlap. |   would cause the archive files of two documents to overlap. | ||||||
|   - This happened when `PAPERLESS_FILENAME_FORMAT` is used and the |   - This happened when `PAPERLESS_FILENAME_FORMAT` is used and the | ||||||
| @ -879,8 +1098,8 @@ This release contains new database migrations. | |||||||
|   - Paperless will now store the archive filename in the database as |   - Paperless will now store the archive filename in the database as | ||||||
|     well instead of deriving it from the original filename, and use |     well instead of deriving it from the original filename, and use | ||||||
|     the same logic for detecting and avoiding filename clashes |     the same logic for detecting and avoiding filename clashes | ||||||
|     that\'s also used for original filenames. |     that's also used for original filenames. | ||||||
|   - The migrations will repair any missing archive files. If you\'re |   - The migrations will repair any missing archive files. If you're | ||||||
|     using tika, ensure that tika is running while performing the |     using tika, ensure that tika is running while performing the | ||||||
|     migration. Docker-compose will take care of that. |     migration. Docker-compose will take care of that. | ||||||
| - Fixed a bug with thumbnail regeneration when TIKA integration was | - Fixed a bug with thumbnail regeneration when TIKA integration was | ||||||
| @ -888,8 +1107,8 @@ This release contains new database migrations. | |||||||
| - Added ASN as a placeholder field to the filename format. | - Added ASN as a placeholder field to the filename format. | ||||||
| - The docker image now comes with built-in shortcuts for most | - The docker image now comes with built-in shortcuts for most | ||||||
|   management commands. These are now the recommended way to execute |   management commands. These are now the recommended way to execute | ||||||
|   management commands, since these also ensure that they\'re always |   management commands, since these also ensure that they're always | ||||||
|   executed as the paperless user and you\'re less likely to run into |   executed as the paperless user and you're less likely to run into | ||||||
|   permission issues. See |   permission issues. See | ||||||
|   `utilities-management-commands`{.interpreted-text role="ref"}. |   `utilities-management-commands`{.interpreted-text role="ref"}. | ||||||
| 
 | 
 | ||||||
| @ -911,10 +1130,7 @@ This release contains new database migrations. | |||||||
| - Live updates to document lists and saved views when new documents | - Live updates to document lists and saved views when new documents | ||||||
|   are added. |   are added. | ||||||
| 
 | 
 | ||||||
|   ::: {.hint} |   !!! tip | ||||||
|   ::: {.title} |  | ||||||
|   Hint |  | ||||||
|   ::: |  | ||||||
| 
 | 
 | ||||||
|   For status notifications and live updates to work, paperless now |   For status notifications and live updates to work, paperless now | ||||||
|   requires an [ASGI](https://asgi.readthedocs.io/en/latest/)-enabled |   requires an [ASGI](https://asgi.readthedocs.io/en/latest/)-enabled | ||||||
| @ -937,7 +1153,6 @@ This release contains new database migrations. | |||||||
| 
 | 
 | ||||||
|   Apache `mod_wsgi` users, see |   Apache `mod_wsgi` users, see | ||||||
|   `this note <faq-mod_wsgi>`{.interpreted-text role="ref"}. |   `this note <faq-mod_wsgi>`{.interpreted-text role="ref"}. | ||||||
|   ::: |  | ||||||
| 
 | 
 | ||||||
| - Paperless now offers suggestions for tags, correspondents and types | - Paperless now offers suggestions for tags, correspondents and types | ||||||
|   on the document detail page. |   on the document detail page. | ||||||
| @ -961,8 +1176,8 @@ This release contains new database migrations. | |||||||
|   - Better icon for document previews. |   - Better icon for document previews. | ||||||
|   - Better info section in the side bar. |   - Better info section in the side bar. | ||||||
|   - Paperless no longer logs to the database. Instead, logs are |   - Paperless no longer logs to the database. Instead, logs are | ||||||
|     written to rotating log files. This solves many \"database is |     written to rotating log files. This solves many "database is | ||||||
|     locked\" issues on Raspberry Pi, especially when SQLite is used. |     locked" issues on Raspberry Pi, especially when SQLite is used. | ||||||
|   - By default, log files are written to `PAPERLESS_DATA_DIR/log/`. |   - By default, log files are written to `PAPERLESS_DATA_DIR/log/`. | ||||||
|     Logging settings can be adjusted with `PAPERLESS_LOGGING_DIR`, |     Logging settings can be adjusted with `PAPERLESS_LOGGING_DIR`, | ||||||
|     `PAPERLESS_LOGROTATE_MAX_SIZE` and |     `PAPERLESS_LOGROTATE_MAX_SIZE` and | ||||||
| @ -991,7 +1206,7 @@ bug reports coming in, I think that this is reasonably stable. | |||||||
|   - Range selection with shift clicking is now possible in the |   - Range selection with shift clicking is now possible in the | ||||||
|     document list. |     document list. | ||||||
|   - Filtering correspondent, type and tag management pages by name. |   - 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 | ### paperless-ng 0.9.14 | ||||||
| 
 | 
 | ||||||
| @ -1053,8 +1268,8 @@ paperless. | |||||||
|   - Fixed an issue with filenames of downloaded files: Dates where |   - Fixed an issue with filenames of downloaded files: Dates where | ||||||
|     off by one day due to timezone issues. |     off by one day due to timezone issues. | ||||||
|   - Searching will continue to work even when the index returns |   - Searching will continue to work even when the index returns | ||||||
|     non-existing documents. This resulted in \"Document does not |     non-existing documents. This resulted in "Document does not | ||||||
|     exist\" errors before. Instead, a warning is logged, indicating |     exist" errors before. Instead, a warning is logged, indicating | ||||||
|     the issue. |     the issue. | ||||||
|   - An issue with the consumer crashing when invalid regular |   - An issue with the consumer crashing when invalid regular | ||||||
|     expression were used was fixed. |     expression were used was fixed. | ||||||
| @ -1095,11 +1310,11 @@ paperless. | |||||||
|     new ASN to a document. |     new ASN to a document. | ||||||
|   - Form field validation: When providing invalid input in a form |   - Form field validation: When providing invalid input in a form | ||||||
|     (such as a duplicate ASN or no name), paperless now has visual |     (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 |   - Paperless disables buttons with network actions (such as save | ||||||
|     and delete) when a network action is active. This indicates that |     and delete) when a network action is active. This indicates that | ||||||
|     something is happening and prevents double clicking. |     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. |     automatically to better support keyboard editing. | ||||||
|   - E-Mail: Added filter rule parameters to allow inline attachments |   - E-Mail: Added filter rule parameters to allow inline attachments | ||||||
|     (watch out for mails with inlined images!) and attachment |     (watch out for mails with inlined images!) and attachment | ||||||
| @ -1108,11 +1323,11 @@ paperless. | |||||||
|     Shamoon](https://github.com/shamoon). This is useful for hiding |     Shamoon](https://github.com/shamoon). This is useful for hiding | ||||||
|     Paperless behind single sign on applications such as |     Paperless behind single sign on applications such as | ||||||
|     [authelia](https://www.authelia.com/). |     [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 |     correctly restores the default filters on saved views. Thanks to | ||||||
|     [Michael Shamoon](https://github.com/shamoon) |     [Michael Shamoon](https://github.com/shamoon) | ||||||
| - Fixes | - 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. |     chosen in one of the filter dropdowns. | ||||||
|   - Clearer error messages when pre and post consumption scripts do |   - Clearer error messages when pre and post consumption scripts do | ||||||
|     not exist. |     not exist. | ||||||
| @ -1128,7 +1343,7 @@ paperless. | |||||||
| ### paperless-ng 0.9.10 | ### paperless-ng 0.9.10 | ||||||
| 
 | 
 | ||||||
| - Bulk editing | - 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. |     got a new interface for the bulk editor. | ||||||
|   - There are some configuration options in the settings to alter |   - There are some configuration options in the settings to alter | ||||||
|     the behavior. |     the behavior. | ||||||
| @ -1137,7 +1352,7 @@ paperless. | |||||||
|     publishes a webmanifest, which is useful for adding the |     publishes a webmanifest, which is useful for adding the | ||||||
|     application to home screens on mobile devices. |     application to home screens on mobile devices. | ||||||
|   - The Paperless-ng logo now navigates to the dashboard. |   - 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. |     or tags assigned. | ||||||
|   - Tags, types and correspondents are now sorted case insensitive. |   - Tags, types and correspondents are now sorted case insensitive. | ||||||
|   - Lots of preparation work for localization support. |   - Lots of preparation work for localization support. | ||||||
| @ -1151,10 +1366,7 @@ paperless. | |||||||
|   - The consumer used to stop working when encountering an |   - The consumer used to stop working when encountering an | ||||||
|     incomplete classifier model file. |     incomplete classifier model file. | ||||||
| 
 | 
 | ||||||
| ::: {.note} | !!! note | ||||||
| ::: {.title} |  | ||||||
| Note |  | ||||||
| ::: |  | ||||||
| 
 | 
 | ||||||
| The bulk delete operations did not update the search index. Therefore, | The bulk delete operations did not update the search index. Therefore, | ||||||
| documents that you deleted remained in the index and caused the search | documents that you deleted remained in the index and caused the search | ||||||
| @ -1165,7 +1377,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 | 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 | `running the management command document_index with the argument reindex <administration-index>`{.interpreted-text | ||||||
| role="ref"}. | role="ref"}. | ||||||
| ::: |  | ||||||
| 
 | 
 | ||||||
| ### paperless-ng 0.9.9 | ### paperless-ng 0.9.9 | ||||||
| 
 | 
 | ||||||
| @ -1176,18 +1387,18 @@ Christmas release! | |||||||
|   - The following operations are available: Add and remove |   - The following operations are available: Add and remove | ||||||
|     correspondents, tags, document types from selected documents, as |     correspondents, tags, document types from selected documents, as | ||||||
|     well as mass-deleting documents. |     well as mass-deleting documents. | ||||||
|   - We\'ve got a more fancy UI in the works that makes these |   - We've got a more fancy UI in the works that makes these | ||||||
|     features more accessible, but that\'s not quite ready yet. |     features more accessible, but that's not quite ready yet. | ||||||
| - Searching | - Searching | ||||||
|   - Paperless now supports searching for similar documents (\"More |   - Paperless now supports searching for similar documents ("More | ||||||
|     like this\") both from the document detail page as well as from |     like this") both from the document detail page as well as from | ||||||
|     individual search results. |     individual search results. | ||||||
|   - A search score indicates how well a document matches the search |   - A search score indicates how well a document matches the search | ||||||
|     query, or how similar a document is to a given reference |     query, or how similar a document is to a given reference | ||||||
|     document. |     document. | ||||||
| - Other additions and changes | - Other additions and changes | ||||||
|   - Clarification in the UI that the fields \"Match\" and \"Is |   - Clarification in the UI that the fields "Match" and "Is | ||||||
|     insensitive\" are not relevant for the Auto matching algorithm. |     insensitive" are not relevant for the Auto matching algorithm. | ||||||
|   - New select interface for tags, types and correspondents allows |   - New select interface for tags, types and correspondents allows | ||||||
|     filtering. This also improves tag selection. Thanks again to |     filtering. This also improves tag selection. Thanks again to | ||||||
|     [Michael Shamoon](https://github.com/shamoon)! |     [Michael Shamoon](https://github.com/shamoon)! | ||||||
| @ -1268,11 +1479,11 @@ This release focusses primarily on many small issues with the UI. | |||||||
|   - Paperless now has proper window titles. |   - Paperless now has proper window titles. | ||||||
|   - Fixed an issue with the small cards when more than 7 tags were |   - Fixed an issue with the small cards when more than 7 tags were | ||||||
|     used. |     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. |     the saved view now, if available in the sidebar. | ||||||
|   - Some indication on the document lists that a filter is active |   - Some indication on the document lists that a filter is active | ||||||
|     was added. |     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. |     a certain tag. | ||||||
|   - The file upload box now shows upload progress. |   - The file upload box now shows upload progress. | ||||||
|   - The document edit page was reorganized. |   - The document edit page was reorganized. | ||||||
| @ -1297,15 +1508,11 @@ This release focusses primarily on many small issues with the UI. | |||||||
|     filenames anymore. It will rather append `_01`, `_02`, etc when |     filenames anymore. It will rather append `_01`, `_02`, etc when | ||||||
|     it detects duplicate filenames. |     it detects duplicate filenames. | ||||||
| 
 | 
 | ||||||
| ::: {.note} | !!! note | ||||||
| ::: {.title} |  | ||||||
| Note |  | ||||||
| ::: |  | ||||||
| 
 | 
 | ||||||
| The changes to the filename format will apply to newly added documents | The changes to the filename format will apply to newly added documents | ||||||
| and changed documents. If you want all files to reflect these changes, | and changed documents. If you want all files to reflect these changes, | ||||||
| execute the `document_renamer` management command. | execute the `document_renamer` management command. | ||||||
| ::: |  | ||||||
| 
 | 
 | ||||||
| ### paperless-ng 0.9.5 | ### paperless-ng 0.9.5 | ||||||
| 
 | 
 | ||||||
| @ -1388,7 +1595,7 @@ primarily. | |||||||
|     need to do this once, since the schema of the search index |     need to do this once, since the schema of the search index | ||||||
|     changed. Paperless keeps the index updated after that whenever |     changed. Paperless keeps the index updated after that whenever | ||||||
|     something changes. |     something changes. | ||||||
|   - Paperless now has spelling corrections (\"Did you mean\") for |   - Paperless now has spelling corrections ("Did you mean") for | ||||||
|     miss-typed queries. |     miss-typed queries. | ||||||
|   - The documentation contains |   - The documentation contains | ||||||
|     `information about the query syntax <basic-searching>`{.interpreted-text |     `information about the query syntax <basic-searching>`{.interpreted-text | ||||||
| @ -1458,7 +1665,7 @@ primarily. | |||||||
|   role="ref"} This features will most likely be removed in future |   role="ref"} This features will most likely be removed in future | ||||||
|   versions. |   versions. | ||||||
| - **Added:** New frontend. Features: | - **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. |     django admin pages. | ||||||
|   - Dashboard. Shows recently scanned documents, or todo notes, or |   - Dashboard. Shows recently scanned documents, or todo notes, or | ||||||
|     other documents at wish. Allows uploading of documents. Shows |     other documents at wish. Allows uploading of documents. Shows | ||||||
| @ -1480,7 +1687,7 @@ primarily. | |||||||
| - **Added:** Archive serial numbers. Assign these to quickly find | - **Added:** Archive serial numbers. Assign these to quickly find | ||||||
|   documents stored in physical binders. |   documents stored in physical binders. | ||||||
| - **Added:** Enabled the internal user management of django. This | - **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 / |   one user to access the website and set some basic permissions / | ||||||
|   renew passwords. |   renew passwords. | ||||||
| - **Modified \[breaking\]:** All new mail consumer with customizable | - **Modified \[breaking\]:** All new mail consumer with customizable | ||||||
| @ -1535,7 +1742,7 @@ primarily. | |||||||
| - **Settings:** | - **Settings:** | ||||||
|   - `PAPERLESS_FORGIVING_OCR` is now default and gone. Reason: Even |   - `PAPERLESS_FORGIVING_OCR` is now default and gone. Reason: Even | ||||||
|     if `langdetect` fails to detect a language, tesseract still does |     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 |     language. Certain language specifics such as umlauts may not get | ||||||
|     picked up properly. |     picked up properly. | ||||||
|   - `PAPERLESS_DEBUG` defaults to `false`. |   - `PAPERLESS_DEBUG` defaults to `false`. | ||||||
| @ -1616,34 +1823,34 @@ primarily. | |||||||
|   [\#442](https://github.com/the-paperless-project/paperless/pull/442). |   [\#442](https://github.com/the-paperless-project/paperless/pull/442). | ||||||
| - Added a `.editorconfig` file to better specify coding style. | - Added a `.editorconfig` file to better specify coding style. | ||||||
| - [Joshua Taillon](https://github.com/jat255) also added some logic to | - [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. |   import. | ||||||
|   [\#440](https://github.com/the-paperless-project/paperless/pull/440) |   [\#440](https://github.com/the-paperless-project/paperless/pull/440) | ||||||
| 
 | 
 | ||||||
| ### 2.5.0 | ### 2.5.0 | ||||||
| 
 | 
 | ||||||
| - **New dependency**: Paperless now optimises thumbnail generation | - **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 |   install that somewhere in your PATH or declare its location in | ||||||
|   `PAPERLESS_OPTIPNG_BINARY`. The Docker image has already been |   `PAPERLESS_OPTIPNG_BINARY`. The Docker image has already been | ||||||
|   updated on the Docker Hub, so you just need to pull the latest one |   updated on the Docker Hub, so you just need to pull the latest one | ||||||
|   from there if you\'re a Docker user. |   from there if you're a Docker user. | ||||||
| - \"Login free\" instances of Paperless were breaking whenever you | - "Login free" instances of Paperless were breaking whenever you | ||||||
|   tried to edit objects in the admin: adding/deleting tags or |   tried to edit objects in the admin: adding/deleting tags or | ||||||
|   correspondents, or even fixing spelling. This was due to the \"user |   correspondents, or even fixing spelling. This was due to the "user | ||||||
|   hack\" we were applying to sessions that weren\'t using a login, as |   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 |   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. |   first user id in the system to this hack user. | ||||||
|   [\#394](https://github.com/the-paperless-project/paperless/issues/394) |   [\#394](https://github.com/the-paperless-project/paperless/issues/394) | ||||||
| - A problem in how we handle slug values on Tags and Correspondents | - A problem in how we handle slug values on Tags and Correspondents | ||||||
|   required a few changes to how we handle this field |   required a few changes to how we handle this field | ||||||
|   [\#393](https://github.com/the-paperless-project/paperless/issues/393): |   [\#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 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 |       restricted to the rules of the `slugify()` function. The slug | ||||||
|       value is still visible in the admin though. |       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 |       correspondents and rewrite the `.slug` values to ones conforming | ||||||
|       to the `slugify()` rules. |       to the `slugify()` rules. | ||||||
|   3.  The consumption process now uses the same rules as `.save()` in |   3.  The consumption process now uses the same rules as `.save()` in | ||||||
| @ -1654,7 +1861,7 @@ primarily. | |||||||
|   Thanks to [Andrew Peng](https://github.com/pengc99) for reporting |   Thanks to [Andrew Peng](https://github.com/pengc99) for reporting | ||||||
|   this. |   this. | ||||||
|   [\#414](https://github.com/the-paperless-project/paperless/issues/414). |   [\#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 |   being installed correctly. [euri10](https://github.com/euri10) was | ||||||
|   quick to provide a fix: |   quick to provide a fix: | ||||||
|   [\#406](https://github.com/the-paperless-project/paperless/issues/406), |   [\#406](https://github.com/the-paperless-project/paperless/issues/406), | ||||||
| @ -1669,13 +1876,13 @@ primarily. | |||||||
| ### 2.4.0 | ### 2.4.0 | ||||||
| 
 | 
 | ||||||
| - A new set of actions are now available thanks to | - 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 |   request! You can now do nifty things like tag documents in bulk, or | ||||||
|   set correspondents in bulk. |   set correspondents in bulk. | ||||||
|   [\#405](https://github.com/the-paperless-project/paperless/pull/405) |   [\#405](https://github.com/the-paperless-project/paperless/pull/405) | ||||||
| - The import/export system is now a little smarter. By default, | - The import/export system is now a little smarter. By default, | ||||||
|   documents are tagged as `unencrypted`, since exports are by their |   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 |   storage type. This allows you to export from an encrypted system and | ||||||
|   import into an unencrypted one, or vice-versa. |   import into an unencrypted one, or vice-versa. | ||||||
| - The migration history has been slightly modified to accommodate | - The migration history has been slightly modified to accommodate | ||||||
| @ -1693,7 +1900,7 @@ primarily. | |||||||
| 
 | 
 | ||||||
| - Support for consuming plain text & markdown documents was added by | - Support for consuming plain text & markdown documents was added by | ||||||
|   [Joshua Taillon](https://github.com/jat255)! This was a |   [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: |   appreciated by the community: | ||||||
|   [\#395](https://github.com/the-paperless-project/paperless/pull/395) |   [\#395](https://github.com/the-paperless-project/paperless/pull/395) | ||||||
|   Thanks also to [David Martin](https://github.com/ddddavidmartin) for |   Thanks also to [David Martin](https://github.com/ddddavidmartin) for | ||||||
| @ -1734,7 +1941,7 @@ primarily. | |||||||
|   lots of different tags: |   lots of different tags: | ||||||
|   [\#391](https://github.com/the-paperless-project/paperless/pull/391). |   [\#391](https://github.com/the-paperless-project/paperless/pull/391). | ||||||
| - [Kilian Koeltzsch](https://github.com/kiliankoe) noticed a bug in | - [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: |   too: | ||||||
|   [\#384](https://github.com/the-paperless-project/paperless/issues/384). |   [\#384](https://github.com/the-paperless-project/paperless/issues/384). | ||||||
| - [erikarvstedt](https://github.com/erikarvstedt) tweaked the | - [erikarvstedt](https://github.com/erikarvstedt) tweaked the | ||||||
| @ -1750,7 +1957,7 @@ primarily. | |||||||
| - [Enno Lohmeier](https://github.com/elohmeier) added three simple | - [Enno Lohmeier](https://github.com/elohmeier) added three simple | ||||||
|   features that make Paperless a lot more user (and developer) |   features that make Paperless a lot more user (and developer) | ||||||
|   friendly: |   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). |       [\#374](https://github.com/the-paperless-project/paperless/pull/374). | ||||||
|   2.  The correspondents & tags pages now have a column showing the |   2.  The correspondents & tags pages now have a column showing the | ||||||
|       number of relevant documents: |       number of relevant documents: | ||||||
| @ -1760,18 +1967,18 @@ primarily. | |||||||
|       environment: |       environment: | ||||||
|       [\#376](https://github.com/the-paperless-project/paperless/pull/376). |       [\#376](https://github.com/the-paperless-project/paperless/pull/376). | ||||||
| - You now also have the ability to customise the interface to your | - 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 |   `overrides.js` in the root of your media directory. Thanks to [Mark | ||||||
|   McFate](https://github.com/SummittDweller) for this idea: |   McFate](https://github.com/SummittDweller) for this idea: | ||||||
|   [\#371](https://github.com/the-paperless-project/paperless/issues/371) |   [\#371](https://github.com/the-paperless-project/paperless/issues/371) | ||||||
| 
 | 
 | ||||||
| ### 2.0.0 | ### 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. | Paperless: we no longer encrypt files with GPG by default. | ||||||
| 
 | 
 | ||||||
| The reasons for this are many, but it boils down to that the encryption | 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 | 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 | 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 | `paperless` user is. In addition to that, _the contents of the documents | ||||||
| @ -1783,7 +1990,7 @@ explicitly set a passphrase in your config file. | |||||||
| 
 | 
 | ||||||
| ### Migrating from 1.x | ### 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, | have `PAPERLESS_PASSPHRASE` set in your config or your environment, | ||||||
| Paperless should continue to operate as it always has. If however, you | Paperless should continue to operate as it always has. If however, you | ||||||
| want to drop encryption too, you only need to do two things: | want to drop encryption too, you only need to do two things: | ||||||
| @ -1813,7 +2020,7 @@ this big change. | |||||||
|   for more information. |   for more information. | ||||||
| - Refactor the use of travis/tox/pytest/coverage into two files: | - Refactor the use of travis/tox/pytest/coverage into two files: | ||||||
|   `.travis.yml` and `setup.cfg`. |   `.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. |   switch over to just using pipenv in the future. | ||||||
| - All for a alternative FreeBSD-friendly location for | - All for a alternative FreeBSD-friendly location for | ||||||
|   `paperless.conf`. Thanks to [Martin |   `paperless.conf`. Thanks to [Martin | ||||||
| @ -1833,7 +2040,7 @@ this big change. | |||||||
|   [\#253](https://github.com/the-paperless-project/paperless/issues/253) |   [\#253](https://github.com/the-paperless-project/paperless/issues/253) | ||||||
|   and |   and | ||||||
|   [\#323](https://github.com/the-paperless-project/paperless/issues/323), |   [\#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 |   for people to host Paperless on a subdirectory. Thanks to [Quentin | ||||||
|   Dawans](https://github.com/ovv) and [Kyle |   Dawans](https://github.com/ovv) and [Kyle | ||||||
|   Lucy](https://github.com/kmlucy) for helping to work this out. |   Lucy](https://github.com/kmlucy) for helping to work this out. | ||||||
| @ -1846,7 +2053,7 @@ this big change. | |||||||
|   very creating Bash skills: |   very creating Bash skills: | ||||||
|   [\#352](https://github.com/the-paperless-project/paperless/pull/352). |   [\#352](https://github.com/the-paperless-project/paperless/pull/352). | ||||||
| - You can now use the search field to find documents by tag thanks to | - 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). |   [\#354](https://github.com/the-paperless-project/paperless/issues/354). | ||||||
| - Inotify is now being used to detect additions to the consume | - Inotify is now being used to detect additions to the consume | ||||||
|   directory thanks to some excellent work from |   directory thanks to some excellent work from | ||||||
| @ -1855,7 +2062,7 @@ this big change. | |||||||
| 
 | 
 | ||||||
| ### 1.3.0 | ### 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 |   to create at least one user. This is thanks to a pull-request from | ||||||
|   [matthewmoto](https://github.com/matthewmoto): |   [matthewmoto](https://github.com/matthewmoto): | ||||||
|   [\#295](https://github.com/the-paperless-project/paperless/pull/295). |   [\#295](https://github.com/the-paperless-project/paperless/pull/295). | ||||||
| @ -1886,7 +2093,7 @@ this big change. | |||||||
|   [\#312](https://github.com/the-paperless-project/paperless/pull/312) |   [\#312](https://github.com/the-paperless-project/paperless/pull/312) | ||||||
|   to fix |   to fix | ||||||
|   [\#306](https://github.com/the-paperless-project/paperless/issues/306). |   [\#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 |   _interesting_ way of handing indexes | ||||||
|   ([\#308](https://github.com/the-paperless-project/paperless/issues/308)). |   ([\#308](https://github.com/the-paperless-project/paperless/issues/308)). | ||||||
|   Thanks to [Simon Taddiken](https://github.com/skuzzle) for reporting |   Thanks to [Simon Taddiken](https://github.com/skuzzle) for reporting | ||||||
| @ -1908,7 +2115,7 @@ this big change. | |||||||
|   already contains text. This can be overridden by setting |   already contains text. This can be overridden by setting | ||||||
|   `PAPERLESS_OCR_ALWAYS=YES` either in your `paperless.conf` or in the |   `PAPERLESS_OCR_ALWAYS=YES` either in your `paperless.conf` or in the | ||||||
|   environment. Note that this also means that Paperless now requires |   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 |   run `pip install -r requirements.txt` after the usual `git pull` to | ||||||
|   properly update. |   properly update. | ||||||
| - [BastianPoe](https://github.com/BastianPoe) has also contributed a | - [BastianPoe](https://github.com/BastianPoe) has also contributed a | ||||||
| @ -1935,7 +2142,7 @@ this big change. | |||||||
| 
 | 
 | ||||||
| ### 1.0.0 | ### 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 |   requirements.txt\`\` after the usual \`\`git pull\`\` to properly | ||||||
|   update**. |   update**. | ||||||
| - Replace the templatetag-based hack we had for document listing in | - Replace the templatetag-based hack we had for document listing in | ||||||
| @ -1956,14 +2163,14 @@ this big change. | |||||||
|   [Pit](https://github.com/pitkley) on |   [Pit](https://github.com/pitkley) on | ||||||
|   [\#268](https://github.com/the-paperless-project/paperless/pull/268). |   [\#268](https://github.com/the-paperless-project/paperless/pull/268). | ||||||
| - Date fields in the admin are now expressed as HTML5 date fields | - 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) |   [\#278](https://github.com/the-paperless-project/paperless/issues/248) | ||||||
| 
 | 
 | ||||||
| ### 0.8.0 | ### 0.8.0 | ||||||
| 
 | 
 | ||||||
| - Paperless can now run in a subdirectory on a host (`/paperless`), | - Paperless can now run in a subdirectory on a host (`/paperless`), | ||||||
|   rather than always running in the root (`/`) thanks to |   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). |   [\#255](https://github.com/the-paperless-project/paperless/pull/255). | ||||||
| 
 | 
 | ||||||
| ### 0.7.0 | ### 0.7.0 | ||||||
| @ -1972,14 +2179,14 @@ this big change. | |||||||
|   [\#235](https://github.com/the-paperless-project/paperless/issues/235), |   [\#235](https://github.com/the-paperless-project/paperless/issues/235), | ||||||
|   Paperless will no longer automatically delete documents attached to |   Paperless will no longer automatically delete documents attached to | ||||||
|   correspondents when those correspondents are themselves deleted. |   correspondents when those correspondents are themselves deleted. | ||||||
|   This was Django\'s default behaviour, but didn\'t make much sense in |   This was Django's default behaviour, but didn't make much sense in | ||||||
|   Paperless\' case. Thanks to [Thomas |   Paperless' case. Thanks to [Thomas | ||||||
|   Brueggemann](https://github.com/thomasbrueggemann) and [David |   Brueggemann](https://github.com/thomasbrueggemann) and [David | ||||||
|   Martin](https://github.com/ddddavidmartin) for their input on this |   Martin](https://github.com/ddddavidmartin) for their input on this | ||||||
|   one. |   one. | ||||||
| - Fix for | - Fix for | ||||||
|   [\#232](https://github.com/the-paperless-project/paperless/issues/232) |   [\#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 |   to [ayounggun](https://github.com/ayounggun) for reporting this one | ||||||
|   and to [Kusti Skytén](https://github.com/kskyten) for posting the |   and to [Kusti Skytén](https://github.com/kskyten) for posting the | ||||||
|   correct solution in the Github issue. |   correct solution in the Github issue. | ||||||
| @ -1990,12 +2197,12 @@ this big change. | |||||||
|   favour of BasicAuth or Django session. |   favour of BasicAuth or Django session. | ||||||
| - Fix the POST API so it actually works. | - Fix the POST API so it actually works. | ||||||
|   [\#236](https://github.com/the-paperless-project/paperless/issues/236) |   [\#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 |   `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 |   only using it for email, this variable has been renamed to | ||||||
|   `PAPERLESS_EMAIL_SECRET`. The old value will still work for a while, |   `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 |   polling feature. Thanks to [Joshua | ||||||
|   Gilman](https://github.com/jmgilman) for all the help with this |   Gilman](https://github.com/jmgilman) for all the help with this | ||||||
|   feature. |   feature. | ||||||
| @ -2003,7 +2210,7 @@ this big change. | |||||||
| ### 0.5.0 | ### 0.5.0 | ||||||
| 
 | 
 | ||||||
| - Support for fuzzy matching in the auto-tagger & auto-correspondent | - 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 |   patch | ||||||
|   [\#220](https://github.com/the-paperless-project/paperless/pull/220). |   [\#220](https://github.com/the-paperless-project/paperless/pull/220). | ||||||
| - Modified the Dockerfile to prepare an export directory | - Modified the Dockerfile to prepare an export directory | ||||||
| @ -2032,7 +2239,7 @@ this big change. | |||||||
| 
 | 
 | ||||||
| - Fix for | - Fix for | ||||||
|   [\#206](https://github.com/the-paperless-project/paperless/issues/206) |   [\#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` |   suffixes like `.PDF` | ||||||
| 
 | 
 | ||||||
| ### 0.4.0 | ### 0.4.0 | ||||||
| @ -2042,7 +2249,7 @@ this big change. | |||||||
|   for more information, but the short explanation is that you can now |   for more information, but the short explanation is that you can now | ||||||
|   attach simple notes & times to documents which are made available |   attach simple notes & times to documents which are made available | ||||||
|   via the API. Currently, the default API (basically just the Django |   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 |   Brueggemann](https://github.com/thomasbrueggemann) over at | ||||||
|   [Paperless |   [Paperless | ||||||
|   Desktop](https://github.com/thomasbrueggemann/paperless-desktop) has |   Desktop](https://github.com/thomasbrueggemann/paperless-desktop) has | ||||||
| @ -2052,16 +2259,16 @@ this big change. | |||||||
| 
 | 
 | ||||||
| - Fix for | - Fix for | ||||||
|   [\#200](https://github.com/the-paperless-project/paperless/issues/200) |   [\#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. |   correspondent or the tags for a document. | ||||||
| - The `content` field is now optional, to allow for the edge case of a | - The `content` field is now optional, to allow for the edge case of a | ||||||
|   purely graphical document. |   purely graphical document. | ||||||
| - You can no longer add documents via the admin. This never worked in | - 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. |   broken form. | ||||||
| - The consumer code has been heavily refactored to support a pluggable | - The consumer code has been heavily refactored to support a pluggable | ||||||
|   interface. Install a paperless consumer via pip and tell paperless |   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. |   Proper documentation is on its way. | ||||||
| 
 | 
 | ||||||
| ### 0.3.5 | ### 0.3.5 | ||||||
| @ -2082,10 +2289,10 @@ this big change. | |||||||
| - Removal of django-suit due to a licensing conflict I bumped into in | - 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 |   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 |   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 |   conflicting with the GPL. Further development will be done against | ||||||
|   the stock Django admin. |   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. |   even on my high-DPI monitor. | ||||||
| - BasicAuth support for document and thumbnail downloads, as well as | - BasicAuth support for document and thumbnail downloads, as well as | ||||||
|   the Push API thanks to \@thomasbrueggemann. See |   the Push API thanks to \@thomasbrueggemann. See | ||||||
| @ -2112,14 +2319,14 @@ this big change. | |||||||
| ### 0.3.0 | ### 0.3.0 | ||||||
| 
 | 
 | ||||||
| - Updated to using django-filter 1.x | - 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. |   misconfigurations. | ||||||
| - Consumer loop time is now configurable for systems with slow writes. | - Consumer loop time is now configurable for systems with slow writes. | ||||||
|   Just set `PAPERLESS_CONSUMER_LOOP_TIME` to a number of seconds. The |   Just set `PAPERLESS_CONSUMER_LOOP_TIME` to a number of seconds. The | ||||||
|   default is 10. |   default is 10. | ||||||
| - As per | - As per | ||||||
|   [\#44](https://github.com/the-paperless-project/paperless/issues/44), |   [\#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`, |   and `PAPERLESS_SECRET`. Please use `PAPERLESS_CONVERT_BINARY`, | ||||||
|   `PAPERLESS_CONSUMPTION_DIR`, and `PAPERLESS_SHARED_SECRET` |   `PAPERLESS_CONSUMPTION_DIR`, and `PAPERLESS_SHARED_SECRET` | ||||||
|   respectively instead. |   respectively instead. | ||||||
| @ -2134,17 +2341,17 @@ this big change. | |||||||
| - [\#146](https://github.com/the-paperless-project/paperless/issues/146): | - [\#146](https://github.com/the-paperless-project/paperless/issues/146): | ||||||
|   Fixed a bug that allowed unauthorised access to the `/fetch` URL. |   Fixed a bug that allowed unauthorised access to the `/fetch` URL. | ||||||
| - [\#131](https://github.com/the-paperless-project/paperless/issues/131): | - [\#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. |   deleted in Paperless. | ||||||
| - [\#121](https://github.com/the-paperless-project/paperless/issues/121): | - [\#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. |   based on the file naming scheme. | ||||||
| - [\#81](https://github.com/the-paperless-project/paperless/issues/81): | - [\#81](https://github.com/the-paperless-project/paperless/issues/81): | ||||||
|   Added a hook to run an arbitrary script after every document is |   Added a hook to run an arbitrary script after every document is | ||||||
|   consumed. |   consumed. | ||||||
| - [\#98](https://github.com/the-paperless-project/paperless/issues/98): | - [\#98](https://github.com/the-paperless-project/paperless/issues/98): | ||||||
|   Added optional environment variables for ImageMagick so that it |   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 |   just running on a low-memory system. Thanks to [Florian | ||||||
|   Harr](https://github.com/evils) for his help on this one. |   Harr](https://github.com/evils) for his help on this one. | ||||||
| - [\#89](https://github.com/the-paperless-project/paperless/issues/89) | - [\#89](https://github.com/the-paperless-project/paperless/issues/89) | ||||||
| @ -2163,8 +2370,8 @@ this big change. | |||||||
| 
 | 
 | ||||||
| ### 0.1.1 | ### 0.1.1 | ||||||
| 
 | 
 | ||||||
| - Potentially **Breaking Change**: All references to \"sender\" in the | - Potentially **Breaking Change**: All references to "sender" in the | ||||||
|   code have been renamed to \"correspondent\" to better reflect the |   code have been renamed to "correspondent" to better reflect the | ||||||
|   nature of the property (one could quite reasonably scan a document |   nature of the property (one could quite reasonably scan a document | ||||||
|   before sending it to someone.) |   before sending it to someone.) | ||||||
| - [\#67](https://github.com/the-paperless-project/paperless/issues/67): | - [\#67](https://github.com/the-paperless-project/paperless/issues/67): | ||||||
| @ -2178,7 +2385,7 @@ this big change. | |||||||
|   contributing conversation that lead to this change. |   contributing conversation that lead to this change. | ||||||
| - [\#20](https://github.com/the-paperless-project/paperless/issues/20): | - [\#20](https://github.com/the-paperless-project/paperless/issues/20): | ||||||
|   Added _unpaper_ support to help in cleaning up the scanned image |   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. |   this one. | ||||||
| - [\#71](https://github.com/the-paperless-project/paperless/issues/71) | - [\#71](https://github.com/the-paperless-project/paperless/issues/71) | ||||||
|   Added (encrypted) thumbnails in anticipation of a proper UI. |   Added (encrypted) thumbnails in anticipation of a proper UI. | ||||||
|  | |||||||
							
								
								
									
										337
									
								
								docs/conf.py
									
									
									
									
									
								
							
							
						
						| @ -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} |  | ||||||
							
								
								
									
										1036
									
								
								docs/configuration.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -1,925 +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`. |  | ||||||
| 
 |  | ||||||
| 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
									
								
							
							
						
						| @ -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. | ||||||
| @ -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 |  | ||||||
							
								
								
									
										125
									
								
								docs/faq.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,125 @@ | |||||||
|  | # 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_usage#file_name_handling). | ||||||
|  | - [The exporter](administration#exporter) 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 [Tika 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. | ||||||
|  | 
 | ||||||
|  | ### _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](setup#less_powerful_devices) 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). | ||||||
|  | 
 | ||||||
|  | ### _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 | ||||||
							
								
								
									
										117
									
								
								docs/faq.rst
									
									
									
									
									
								
							
							
						
						| @ -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
									
								
							
							
						
						| @ -0,0 +1,138 @@ | |||||||
|  | <div class="grid-left" markdown> | ||||||
|  | {.index-logo} | ||||||
|  | {.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 target=\_blank } | ||||||
|  | 
 | ||||||
|  | </div> | ||||||
|  | <div class="grid-right" markdown> | ||||||
|  | {.index-screenshot} | ||||||
|  | {.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: | ||||||
|  | 
 | ||||||
|  | [](assets/screenshots/dashboard.png) | ||||||
|  | 
 | ||||||
|  | The document list provides three different styles to scroll through your | ||||||
|  | documents: | ||||||
|  | 
 | ||||||
|  | [](assets/screenshots/documents-table.png) | ||||||
|  | 
 | ||||||
|  | [](assets/screenshots/documents-smallcards.png) | ||||||
|  | 
 | ||||||
|  | [](assets/screenshots/documents-largecards.png) | ||||||
|  | 
 | ||||||
|  | Paperless-ngx also supports dark mode: | ||||||
|  | 
 | ||||||
|  | [](assets/screenshots/documents-smallcards-dark.png) | ||||||
|  | 
 | ||||||
|  | Extensive filtering mechanisms: | ||||||
|  | 
 | ||||||
|  | [](assets/screenshots/documents-filter.png) | ||||||
|  | 
 | ||||||
|  | Bulk editing of document tags, correspondents, etc.: | ||||||
|  | 
 | ||||||
|  | [](assets/screenshots/bulk-edit.png) | ||||||
|  | 
 | ||||||
|  | Side-by-side editing of documents: | ||||||
|  | 
 | ||||||
|  | [](assets/screenshots/editing.png) | ||||||
|  | 
 | ||||||
|  | Tag editing. This looks about the same for correspondents and document | ||||||
|  | types. | ||||||
|  | 
 | ||||||
|  | [](assets/screenshots/new-tag.png) | ||||||
|  | 
 | ||||||
|  | Searching provides auto complete and highlights the results. | ||||||
|  | 
 | ||||||
|  | [](assets/screenshots/search-preview.png) | ||||||
|  | 
 | ||||||
|  | [](assets/screenshots/search-results.png) | ||||||
|  | 
 | ||||||
|  | Fancy mail filters! | ||||||
|  | 
 | ||||||
|  | [](assets/screenshots/mail-rules-edited.png) | ||||||
|  | 
 | ||||||
|  | Mobile devices are supported. | ||||||
|  | 
 | ||||||
|  | [](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). | ||||||
| @ -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 |  | ||||||
| @ -1 +0,0 @@ | |||||||
| myst-parser==0.18.1 |  | ||||||
| @ -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>`_. |  | ||||||
| @ -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 |  | ||||||
							
								
								
									
										856
									
								
								docs/setup.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,856 @@ | |||||||
|  | ## 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 [Docker setup](#docker_hub) 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 to have a place for your | ||||||
|  |     configuration files and consumption directory. | ||||||
|  | 
 | ||||||
|  |     ```shell-session | ||||||
|  |     $ mkdir -v ~/paperless-ngx | ||||||
|  |     ``` | ||||||
|  | 
 | ||||||
|  | 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. | ||||||
|  | 
 | ||||||
|  |     !!! 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` or | ||||||
|  |         `docker -v` | ||||||
|  | 
 | ||||||
|  |         See the [Docker installation guide](https://docs.docker.com/engine/install/) 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](https://docs.docker.com/compose/install/linux/) 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: | ||||||
|  | 
 | ||||||
|  |     ```yaml | ||||||
|  |     - ./consume:/usr/src/paperless/consume | ||||||
|  |     ``` | ||||||
|  | 
 | ||||||
|  |     Replace the part BEFORE the colon with a local directory of your | ||||||
|  |     choice: | ||||||
|  | 
 | ||||||
|  |     ```yaml | ||||||
|  |     - /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): | ||||||
|  | 
 | ||||||
|  |     ```yaml | ||||||
|  |     ports: | ||||||
|  |       - 8000:8000 | ||||||
|  |     ``` | ||||||
|  | 
 | ||||||
|  |     Replace the part BEFORE the colon with a port of your choice: | ||||||
|  | 
 | ||||||
|  |     ```yaml | ||||||
|  |     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"` to check. | ||||||
|  | 
 | ||||||
|  |     !!! note | ||||||
|  | 
 | ||||||
|  |         You can copy any setting from the file `paperless.conf.example` and | ||||||
|  |         paste it here. Have a look at [configuration](/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 | ||||||
|  | 
 | ||||||
|  |     !!! 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 [Docker Setup](setup#docker_hub) | ||||||
|  |     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](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]{.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](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. | ||||||
|  | 
 | ||||||
|  |     ```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](configuration#software_tweaks) 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 [documentation](#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](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 [Docker setup](setup#docker_hub) 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 [MySQL caveats](advanced##mysql-caveats) for details. | ||||||
|  | 
 | ||||||
|  | !!! warning | ||||||
|  | 
 | ||||||
|  |     MySQL also enforces limits on maximum lengths, but does so differently than | ||||||
|  |     PostgreSQL.  It may not be possible to migrate to MySQL due to this. | ||||||
|  | 
 | ||||||
|  | 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](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: | ||||||
|  | 
 | ||||||
|  |         ``` 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](configuration). | ||||||
|  | 
 | ||||||
|  | !!! 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](configuration#hosting-and-security) docs. | ||||||
|  | 
 | ||||||
|  | Also read | ||||||
|  | [this](https://channels.readthedocs.io/en/stable/deploying.html#nginx-supervisor-ubuntu), | ||||||
|  | towards the end of the section. | ||||||
							
								
								
									
										846
									
								
								docs/setup.rst
									
									
									
									
									
								
							
							
						
						| @ -1,846 +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. |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| .. _setup-sqlite_to_psql: |  | ||||||
| 
 |  | ||||||
| Moving data from SQLite to PostgreSQL |  | ||||||
| ===================================== |  | ||||||
| 
 |  | ||||||
| Moving your data from SQLite to PostgreSQL is done via executing a series of django |  | ||||||
| management commands as below. |  | ||||||
| 
 |  | ||||||
| .. 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. |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 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. |  | ||||||
							
								
								
									
										334
									
								
								docs/troubleshooting.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,334 @@ | |||||||
|  | # 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 | ||||||
|  | # The gotenberg chromium route is used to convert .eml files. We do not | ||||||
|  | # want to allow external content like tracking pixels or even javascript. | ||||||
|  | command: | ||||||
|  |   - 'gotenberg' | ||||||
|  |   - '--chromium-disable-javascript=true' | ||||||
|  |   - '--chromium-allow-list=file:///tmp/.*' | ||||||
|  |   - '--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 [Docker setup](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: | ||||||
|  | 
 | ||||||
|  | ```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. | ||||||
| @ -1,319 +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. |  | ||||||
							
								
								
									
										483
									
								
								docs/usage.md
									
									
									
									
									
										Normal 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 | ||||||
|  |   [recommended workflow](#usage-reccomended_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. | ||||||
|  | 
 | ||||||
|  | ## 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 [docs][api#file-uploads] | ||||||
|  | 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. | ||||||
|  | 
 | ||||||
|  | {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](advanced_usage#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. | ||||||
|  | 
 | ||||||
|  | ## 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. | ||||||
| @ -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. |  | ||||||
| @ -95,6 +95,7 @@ echo "============================" | |||||||
| echo "" | echo "" | ||||||
| echo "The URL paperless will be available at. This is required if the" | echo "The URL paperless will be available at. This is required if the" | ||||||
| echo "installation will be accessible via the web, otherwise can be left blank." | echo "installation will be accessible via the web, otherwise can be left blank." | ||||||
|  | echo "Example: https://paperless.example.com" | ||||||
| echo "" | echo "" | ||||||
| 
 | 
 | ||||||
| ask "URL" "" | ask "URL" "" | ||||||
| @ -112,6 +113,8 @@ echo "" | |||||||
| echo "Paperless requires you to configure the current time zone correctly." | echo "Paperless requires you to configure the current time zone correctly." | ||||||
| echo "Otherwise, the dates of your documents may appear off by one day," | echo "Otherwise, the dates of your documents may appear off by one day," | ||||||
| echo "depending on where you are on earth." | echo "depending on where you are on earth." | ||||||
|  | echo "Example: Europe/Berlin" | ||||||
|  | echo "See here for a list: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones" | ||||||
| echo "" | echo "" | ||||||
| 
 | 
 | ||||||
| ask "Current time zone" "$default_time_zone" | ask "Current time zone" "$default_time_zone" | ||||||
|  | |||||||
							
								
								
									
										62
									
								
								mkdocs.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,62 @@ | |||||||
|  | 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 | ||||||
|  |   favicon: assets/favicon.png | ||||||
|  | repo_url: https://github.com/paperless-ngx/paperless-ngx | ||||||
|  | edit_uri: blob/main/docs/ | ||||||
|  | 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 © 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 | ||||||
| @ -1,5 +1,5 @@ | |||||||
| # Have a look at the docs for documentation. | # Have a look at the docs for documentation. | ||||||
| # https://paperless-ngx.readthedocs.io/en/latest/configuration.html | # https://docs.paperless-ngx.com/configuration/ | ||||||
| 
 | 
 | ||||||
| # Debug. Only enable this for development. | # Debug. Only enable this for development. | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -2,5 +2,5 @@ | |||||||
| 
 | 
 | ||||||
| docker run -p 5432:5432 -e POSTGRES_PASSWORD=password -v paperless_pgdata:/var/lib/postgresql/data -d postgres:13 | docker run -p 5432:5432 -e POSTGRES_PASSWORD=password -v paperless_pgdata:/var/lib/postgresql/data -d postgres:13 | ||||||
| docker run -d -p 6379:6379 redis:latest | docker run -d -p 6379:6379 redis:latest | ||||||
| docker run -p 3000:3000 -d gotenberg/gotenberg:7.6 | docker run -p 3000:3000 -d gotenberg/gotenberg:7.6 gotenberg --chromium-disable-javascript=true --chromium-allow-list="file:///tmp/.*" | ||||||
| docker run -p 9998:9998 -d ghcr.io/paperless-ngx/tika:latest | docker run -p 9998:9998 -d ghcr.io/paperless-ngx/tika:latest | ||||||
|  | |||||||
| @ -35,6 +35,16 @@ describe('settings', () => { | |||||||
|             req.reply(response) |             req.reply(response) | ||||||
|           } |           } | ||||||
|         ).as('savedViews') |         ).as('savedViews') | ||||||
|  | 
 | ||||||
|  |         cy.intercept('http://localhost:8000/api/mail_accounts/*', { | ||||||
|  |           fixture: 'mail_accounts/mail_accounts.json', | ||||||
|  |         }) | ||||||
|  |         cy.intercept('http://localhost:8000/api/mail_rules/*', { | ||||||
|  |           fixture: 'mail_rules/mail_rules.json', | ||||||
|  |         }).as('mailRules') | ||||||
|  |         cy.intercept('http://localhost:8000/api/tasks/', { | ||||||
|  |           fixture: 'tasks/tasks.json', | ||||||
|  |         }) | ||||||
|       }) |       }) | ||||||
| 
 | 
 | ||||||
|       cy.fixture('documents/documents.json').then((documentsJson) => { |       cy.fixture('documents/documents.json').then((documentsJson) => { | ||||||
| @ -48,7 +58,6 @@ describe('settings', () => { | |||||||
| 
 | 
 | ||||||
|     cy.viewport(1024, 1600) |     cy.viewport(1024, 1600) | ||||||
|     cy.visit('/settings') |     cy.visit('/settings') | ||||||
|     cy.wait('@savedViews') |  | ||||||
|   }) |   }) | ||||||
| 
 | 
 | ||||||
|   it('should activate / deactivate save button when settings change and are saved', () => { |   it('should activate / deactivate save button when settings change and are saved', () => { | ||||||
| @ -77,16 +86,16 @@ describe('settings', () => { | |||||||
|   }) |   }) | ||||||
| 
 | 
 | ||||||
|   it('should remove saved view from sidebar when unset', () => { |   it('should remove saved view from sidebar when unset', () => { | ||||||
|     cy.contains('a', 'Saved views').click() |     cy.contains('a', 'Saved views').click().wait(2000) | ||||||
|     cy.get('#show_in_sidebar_1').click() |     cy.get('#show_in_sidebar_1').click() | ||||||
|     cy.contains('button', 'Save').click().wait('@savedViews') |     cy.contains('button', 'Save').click().wait('@savedViews').wait(2000) | ||||||
|     cy.contains('li', 'Inbox').should('not.exist') |     cy.contains('li', 'Inbox').should('not.exist') | ||||||
|   }) |   }) | ||||||
| 
 | 
 | ||||||
|   it('should remove saved view from dashboard when unset', () => { |   it('should remove saved view from dashboard when unset', () => { | ||||||
|     cy.contains('a', 'Saved views').click() |     cy.contains('a', 'Saved views').click() | ||||||
|     cy.get('#show_on_dashboard_1').click() |     cy.get('#show_on_dashboard_1').click() | ||||||
|     cy.contains('button', 'Save').click().wait('@savedViews') |     cy.contains('button', 'Save').click().wait('@savedViews').wait(2000) | ||||||
|     cy.visit('/dashboard') |     cy.visit('/dashboard') | ||||||
|     cy.get('app-saved-view-widget').contains('Inbox').should('not.exist') |     cy.get('app-saved-view-widget').contains('Inbox').should('not.exist') | ||||||
|   }) |   }) | ||||||
|  | |||||||
| @ -44,6 +44,39 @@ describe('tasks', () => { | |||||||
|       }) |       }) | ||||||
|   }) |   }) | ||||||
| 
 | 
 | ||||||
|  |   it('should correctly switch between task tabs', () => { | ||||||
|  |     cy.get('tbody').find('tr:visible').its('length').should('eq', 10) // double because collapsible result tr
 | ||||||
|  |     cy.wait(500) // stabilizes the test, for some reason...
 | ||||||
|  |     cy.get('app-tasks') | ||||||
|  |       .find('a:visible') | ||||||
|  |       .contains('Queued') | ||||||
|  |       .first() | ||||||
|  |       .click() | ||||||
|  |       .wait(2000) | ||||||
|  |       .then(() => { | ||||||
|  |         cy.get('tbody').find('tr:visible').should('not.exist') | ||||||
|  |       }) | ||||||
|  |     cy.get('app-tasks') | ||||||
|  |       .find('a:visible') | ||||||
|  |       .contains('Started') | ||||||
|  |       .first() | ||||||
|  |       .click() | ||||||
|  |       .wait(2000) | ||||||
|  |       .then(() => { | ||||||
|  |         cy.get('tbody').find('tr:visible').its('length').should('eq', 2) // double because collapsible result tr
 | ||||||
|  |       }) | ||||||
|  |     cy.get('app-tasks') | ||||||
|  |       .find('a:visible') | ||||||
|  |       .contains('Complete') | ||||||
|  |       .first() | ||||||
|  |       .click() | ||||||
|  |       .wait('@tasks') | ||||||
|  |       .wait(2000) | ||||||
|  |       .then(() => { | ||||||
|  |         cy.get('tbody').find('tr:visible').its('length').should('eq', 12) // double because collapsible result tr
 | ||||||
|  |       }) | ||||||
|  |   }) | ||||||
|  | 
 | ||||||
|   it('should allow toggling all tasks in list and warn on dismiss', () => { |   it('should allow toggling all tasks in list and warn on dismiss', () => { | ||||||
|     cy.get('thead').find('input[type="checkbox"]').first().click() |     cy.get('thead').find('input[type="checkbox"]').first().click() | ||||||
|     cy.get('body').find('button').contains('Dismiss selected').first().click() |     cy.get('body').find('button').contains('Dismiss selected').first().click() | ||||||
|  | |||||||
							
								
								
									
										27
									
								
								src-ui/cypress/fixtures/mail_accounts/mail_accounts.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,27 @@ | |||||||
|  | { | ||||||
|  |     "count": 2, | ||||||
|  |     "next": null, | ||||||
|  |     "previous": null, | ||||||
|  |     "results": [ | ||||||
|  |         { | ||||||
|  |             "id": 1, | ||||||
|  |             "name": "IMAP Server", | ||||||
|  |             "imap_server": "imap.example.com", | ||||||
|  |             "imap_port": 993, | ||||||
|  |             "imap_security": 2, | ||||||
|  |             "username": "inbox@example.com", | ||||||
|  |             "password": "pass", | ||||||
|  |             "character_set": "UTF-8" | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "id": 2, | ||||||
|  |             "name": "Gmail", | ||||||
|  |             "imap_server": "imap.gmail.com", | ||||||
|  |             "imap_port": 993, | ||||||
|  |             "imap_security": 2, | ||||||
|  |             "username": "user@gmail.com", | ||||||
|  |             "password": "pass", | ||||||
|  |             "character_set": "UTF-8" | ||||||
|  |         } | ||||||
|  |     ] | ||||||
|  | } | ||||||
							
								
								
									
										29
									
								
								src-ui/cypress/fixtures/mail_rules/mail_rules.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,29 @@ | |||||||
|  | { | ||||||
|  |     "count": 1, | ||||||
|  |     "next": null, | ||||||
|  |     "previous": null, | ||||||
|  |     "results": [ | ||||||
|  |         { | ||||||
|  |             "id": 1, | ||||||
|  |             "name": "Gmail", | ||||||
|  |             "account": 2, | ||||||
|  |             "folder": "INBOX", | ||||||
|  |             "filter_from": null, | ||||||
|  |             "filter_subject": "[paperless]", | ||||||
|  |             "filter_body": null, | ||||||
|  |             "filter_attachment_filename": null, | ||||||
|  |             "maximum_age": 30, | ||||||
|  |             "action": 3, | ||||||
|  |             "action_parameter": null, | ||||||
|  |             "assign_title_from": 1, | ||||||
|  |             "assign_tags": [ | ||||||
|  |                 9 | ||||||
|  |             ], | ||||||
|  |             "assign_correspondent_from": 1, | ||||||
|  |             "assign_correspondent": 2, | ||||||
|  |             "assign_document_type": null, | ||||||
|  |             "order": 0, | ||||||
|  |             "attachment_type": 2 | ||||||
|  |         } | ||||||
|  |     ] | ||||||
|  | } | ||||||
| @ -1 +1,44 @@ | |||||||
| {"count":3,"next":null,"previous":null,"results":[{"id":1,"name":"Inbox","show_on_dashboard":true,"show_in_sidebar":true,"sort_field":"created","sort_reverse":true,"filter_rules":[{"rule_type":6,"value":"18"}]},{"id":2,"name":"Recently Added","show_on_dashboard":true,"show_in_sidebar":false,"sort_field":"created","sort_reverse":true,"filter_rules":[]},{"id":11,"name":"Taxes","show_on_dashboard":false,"show_in_sidebar":true,"sort_field":"created","sort_reverse":true,"filter_rules":[{"rule_type":6,"value":"39"}]}]} | { | ||||||
|  |     "count": 3, | ||||||
|  |     "next": null, | ||||||
|  |     "previous": null, | ||||||
|  |     "results": [ | ||||||
|  |         { | ||||||
|  |             "id": 1, | ||||||
|  |             "name": "Inbox", | ||||||
|  |             "show_on_dashboard": true, | ||||||
|  |             "show_in_sidebar": true, | ||||||
|  |             "sort_field": "created", | ||||||
|  |             "sort_reverse": true, | ||||||
|  |             "filter_rules": [ | ||||||
|  |                 { | ||||||
|  |                     "rule_type": 6, | ||||||
|  |                     "value": "18" | ||||||
|  |                 } | ||||||
|  |             ] | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "id": 2, | ||||||
|  |             "name": "Recently Added", | ||||||
|  |             "show_on_dashboard": true, | ||||||
|  |             "show_in_sidebar": false, | ||||||
|  |             "sort_field": "created", | ||||||
|  |             "sort_reverse": true, | ||||||
|  |             "filter_rules": [] | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "id": 11, | ||||||
|  |             "name": "Taxes", | ||||||
|  |             "show_on_dashboard": false, | ||||||
|  |             "show_in_sidebar": true, | ||||||
|  |             "sort_field": "created", | ||||||
|  |             "sort_reverse": true, | ||||||
|  |             "filter_rules": [ | ||||||
|  |                 { | ||||||
|  |                     "rule_type": 6, | ||||||
|  |                     "value": "39" | ||||||
|  |                 } | ||||||
|  |             ] | ||||||
|  |         } | ||||||
|  |     ] | ||||||
|  | } | ||||||
|  | |||||||
							
								
								
									
										1006
									
								
								src-ui/messages.xlf
									
									
									
									
									
								
							
							
						
						
							
								
								
									
										2907
									
								
								src-ui/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						| @ -23,22 +23,22 @@ | |||||||
|     "@angular/router": "~14.2.8", |     "@angular/router": "~14.2.8", | ||||||
|     "@ng-bootstrap/ng-bootstrap": "^13.0.0", |     "@ng-bootstrap/ng-bootstrap": "^13.0.0", | ||||||
|     "@ng-select/ng-select": "^9.0.2", |     "@ng-select/ng-select": "^9.0.2", | ||||||
|     "@ngneat/dirty-check-forms": "^3.0.2", |     "@ngneat/dirty-check-forms": "^3.0.3", | ||||||
|     "@popperjs/core": "^2.11.6", |     "@popperjs/core": "^2.11.6", | ||||||
|     "bootstrap": "^5.2.1", |     "bootstrap": "^5.2.1", | ||||||
|     "file-saver": "^2.0.5", |     "file-saver": "^2.0.5", | ||||||
|     "ng2-pdf-viewer": "^9.1.2", |     "ng2-pdf-viewer": "^9.1.2", | ||||||
|     "ngx-color": "^8.0.3", |     "ngx-color": "^8.0.3", | ||||||
|     "ngx-cookie-service": "^14.0.1", |     "ngx-cookie-service": "^14.0.1", | ||||||
|     "ngx-file-drop": "^14.0.1", |     "ngx-file-drop": "^14.0.2", | ||||||
|     "ngx-ui-tour-ng-bootstrap": "^11.1.0", |     "ngx-ui-tour-ng-bootstrap": "^11.1.0", | ||||||
|     "rxjs": "~7.5.7", |     "rxjs": "~7.5.7", | ||||||
|     "tslib": "^2.3.1", |     "tslib": "^2.4.1", | ||||||
|     "uuid": "^9.0.0", |     "uuid": "^9.0.0", | ||||||
|     "zone.js": "~0.11.8" |     "zone.js": "~0.11.8" | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "@angular-builders/jest": "14.0.1", |     "@angular-builders/jest": "14.1.0", | ||||||
|     "@angular-devkit/build-angular": "~14.2.7", |     "@angular-devkit/build-angular": "~14.2.7", | ||||||
|     "@angular/cli": "~14.2.7", |     "@angular/cli": "~14.2.7", | ||||||
|     "@angular/compiler-cli": "~14.2.8", |     "@angular/compiler-cli": "~14.2.8", | ||||||
| @ -48,7 +48,7 @@ | |||||||
|     "concurrently": "7.4.0", |     "concurrently": "7.4.0", | ||||||
|     "jest": "28.1.3", |     "jest": "28.1.3", | ||||||
|     "jest-environment-jsdom": "^29.2.2", |     "jest-environment-jsdom": "^29.2.2", | ||||||
|     "jest-preset-angular": "^12.2.2", |     "jest-preset-angular": "^12.2.3", | ||||||
|     "ts-node": "~10.9.1", |     "ts-node": "~10.9.1", | ||||||
|     "tslint": "~6.1.3", |     "tslint": "~6.1.3", | ||||||
|     "typescript": "~4.8.4", |     "typescript": "~4.8.4", | ||||||
|  | |||||||
| @ -154,6 +154,12 @@ const routes: Routes = [ | |||||||
|           }, |           }, | ||||||
|         }, |         }, | ||||||
|       }, |       }, | ||||||
|  |       { | ||||||
|  |         path: 'settings/:section', | ||||||
|  |         component: SettingsComponent, | ||||||
|  |         canDeactivate: [DirtyFormGuard], | ||||||
|  |       }, | ||||||
|  |       { path: 'tasks', component: TasksComponent }, | ||||||
|     ], |     ], | ||||||
|   }, |   }, | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -135,6 +135,10 @@ export class AppComponent implements OnInit, OnDestroy { | |||||||
|         } |         } | ||||||
|       }) |       }) | ||||||
| 
 | 
 | ||||||
|  |     const prevBtnTitle = $localize`Prev` | ||||||
|  |     const nextBtnTitle = $localize`Next` | ||||||
|  |     const endBtnTitle = $localize`End` | ||||||
|  | 
 | ||||||
|     this.tourService.initialize([ |     this.tourService.initialize([ | ||||||
|       { |       { | ||||||
|         anchorId: 'tour.dashboard', |         anchorId: 'tour.dashboard', | ||||||
| @ -142,12 +146,18 @@ export class AppComponent implements OnInit, OnDestroy { | |||||||
|         route: '/dashboard', |         route: '/dashboard', | ||||||
|         enableBackdrop: true, |         enableBackdrop: true, | ||||||
|         delayAfterNavigation: 500, |         delayAfterNavigation: 500, | ||||||
|  |         prevBtnTitle, | ||||||
|  |         nextBtnTitle, | ||||||
|  |         endBtnTitle, | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         anchorId: 'tour.upload-widget', |         anchorId: 'tour.upload-widget', | ||||||
|         content: $localize`Drag-and-drop documents here to start uploading or place them in the consume folder. You can also drag-and-drop documents anywhere on all other pages of the web app. Once you do, Paperless-ngx will start training its machine learning algorithms.`, |         content: $localize`Drag-and-drop documents here to start uploading or place them in the consume folder. You can also drag-and-drop documents anywhere on all other pages of the web app. Once you do, Paperless-ngx will start training its machine learning algorithms.`, | ||||||
|         route: '/dashboard', |         route: '/dashboard', | ||||||
|         enableBackdrop: true, |         enableBackdrop: true, | ||||||
|  |         prevBtnTitle, | ||||||
|  |         nextBtnTitle, | ||||||
|  |         endBtnTitle, | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         anchorId: 'tour.documents', |         anchorId: 'tour.documents', | ||||||
| @ -157,6 +167,9 @@ export class AppComponent implements OnInit, OnDestroy { | |||||||
|         placement: 'bottom', |         placement: 'bottom', | ||||||
|         enableBackdrop: true, |         enableBackdrop: true, | ||||||
|         disableScrollToAnchor: true, |         disableScrollToAnchor: true, | ||||||
|  |         prevBtnTitle, | ||||||
|  |         nextBtnTitle, | ||||||
|  |         endBtnTitle, | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         anchorId: 'tour.documents-filter-editor', |         anchorId: 'tour.documents-filter-editor', | ||||||
| @ -164,35 +177,45 @@ export class AppComponent implements OnInit, OnDestroy { | |||||||
|         route: '/documents?sort=created&reverse=1&page=1', |         route: '/documents?sort=created&reverse=1&page=1', | ||||||
|         placement: 'bottom', |         placement: 'bottom', | ||||||
|         enableBackdrop: true, |         enableBackdrop: true, | ||||||
|  |         prevBtnTitle, | ||||||
|  |         nextBtnTitle, | ||||||
|  |         endBtnTitle, | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         anchorId: 'tour.documents-views', |         anchorId: 'tour.documents-views', | ||||||
|         content: $localize`Any combination of filters can be saved as a 'view' which can then be displayed on the dashboard and / or sidebar.`, |         content: $localize`Any combination of filters can be saved as a 'view' which can then be displayed on the dashboard and / or sidebar.`, | ||||||
|         route: '/documents?sort=created&reverse=1&page=1', |         route: '/documents?sort=created&reverse=1&page=1', | ||||||
|         enableBackdrop: true, |         enableBackdrop: true, | ||||||
|  |         prevBtnTitle, | ||||||
|  |         nextBtnTitle, | ||||||
|  |         endBtnTitle, | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         anchorId: 'tour.tags', |         anchorId: 'tour.tags', | ||||||
|         content: $localize`Tags, correspondents, document types and storage paths can all be managed using these pages. They can also be created from the document edit view.`, |         content: $localize`Tags, correspondents, document types and storage paths can all be managed using these pages. They can also be created from the document edit view.`, | ||||||
|         route: '/tags', |         route: '/tags', | ||||||
|         enableBackdrop: true, |         enableBackdrop: true, | ||||||
|  |         prevBtnTitle, | ||||||
|  |         nextBtnTitle, | ||||||
|  |         endBtnTitle, | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         anchorId: 'tour.file-tasks', |         anchorId: 'tour.file-tasks', | ||||||
|         content: $localize`File Tasks shows you documents that have been consumed, are waiting to be, or may have failed during the process.`, |         content: $localize`File Tasks shows you documents that have been consumed, are waiting to be, or may have failed during the process.`, | ||||||
|         route: '/tasks', |         route: '/tasks', | ||||||
|         enableBackdrop: true, |         enableBackdrop: true, | ||||||
|  |         prevBtnTitle, | ||||||
|  |         nextBtnTitle, | ||||||
|  |         endBtnTitle, | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         anchorId: 'tour.settings', |         anchorId: 'tour.settings', | ||||||
|         content: $localize`Check out the settings for various tweaks to the web app or to toggle settings for saved views.`, |         content: $localize`Check out the settings for various tweaks to the web app, toggle settings for saved views or setup e-mail checking.`, | ||||||
|         route: '/settings', |         route: '/settings', | ||||||
|         enableBackdrop: true, |         enableBackdrop: true, | ||||||
|       }, |         prevBtnTitle, | ||||||
|       { |         nextBtnTitle, | ||||||
|         anchorId: 'tour.admin', |         endBtnTitle, | ||||||
|         content: $localize`The Admin area contains more advanced controls as well as the settings for automatic e-mail fetching.`, |  | ||||||
|         enableBackdrop: true, |  | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         anchorId: 'tour.outro', |         anchorId: 'tour.outro', | ||||||
| @ -202,6 +225,9 @@ export class AppComponent implements OnInit, OnDestroy { | |||||||
|           '<br/><br/>' + |           '<br/><br/>' + | ||||||
|           $localize`Lastly, on behalf of every contributor to this community-supported project, thank you for using Paperless-ngx!`, |           $localize`Lastly, on behalf of every contributor to this community-supported project, thank you for using Paperless-ngx!`, | ||||||
|         route: '/dashboard', |         route: '/dashboard', | ||||||
|  |         prevBtnTitle, | ||||||
|  |         nextBtnTitle, | ||||||
|  |         endBtnTitle, | ||||||
|       }, |       }, | ||||||
|     ]) |     ]) | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -39,6 +39,7 @@ import { NgxFileDropModule } from 'ngx-file-drop' | |||||||
| import { TextComponent } from './components/common/input/text/text.component' | import { TextComponent } from './components/common/input/text/text.component' | ||||||
| import { SelectComponent } from './components/common/input/select/select.component' | import { SelectComponent } from './components/common/input/select/select.component' | ||||||
| import { CheckComponent } from './components/common/input/check/check.component' | import { CheckComponent } from './components/common/input/check/check.component' | ||||||
|  | import { PasswordComponent } from './components/common/input/password/password.component' | ||||||
| import { SaveViewConfigDialogComponent } from './components/document-list/save-view-config-dialog/save-view-config-dialog.component' | import { SaveViewConfigDialogComponent } from './components/document-list/save-view-config-dialog/save-view-config-dialog.component' | ||||||
| import { TagsComponent } from './components/common/input/tags/tags.component' | import { TagsComponent } from './components/common/input/tags/tags.component' | ||||||
| import { IfPermissionsDirective } from './directives/if-permissions.directive' | import { IfPermissionsDirective } from './directives/if-permissions.directive' | ||||||
| @ -81,6 +82,8 @@ import { TourNgBootstrapModule } from 'ngx-ui-tour-ng-bootstrap' | |||||||
| import { UserEditDialogComponent } from './components/common/edit-dialog/user-edit-dialog/user-edit-dialog.component' | import { UserEditDialogComponent } from './components/common/edit-dialog/user-edit-dialog/user-edit-dialog.component' | ||||||
| import { GroupEditDialogComponent } from './components/common/edit-dialog/group-edit-dialog/group-edit-dialog.component' | import { GroupEditDialogComponent } from './components/common/edit-dialog/group-edit-dialog/group-edit-dialog.component' | ||||||
| import { PermissionsSelectComponent } from './components/common/permissions-select/permissions-select.component' | import { PermissionsSelectComponent } from './components/common/permissions-select/permissions-select.component' | ||||||
|  | import { MailAccountEditDialogComponent } from './components/common/edit-dialog/mail-account-edit-dialog/mail-account-edit-dialog.component' | ||||||
|  | import { MailRuleEditDialogComponent } from './components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component' | ||||||
| 
 | 
 | ||||||
| import localeBe from '@angular/common/locales/be' | import localeBe from '@angular/common/locales/be' | ||||||
| import localeCs from '@angular/common/locales/cs' | import localeCs from '@angular/common/locales/cs' | ||||||
| @ -162,6 +165,7 @@ function initializeApp(settings: SettingsService) { | |||||||
|     TextComponent, |     TextComponent, | ||||||
|     SelectComponent, |     SelectComponent, | ||||||
|     CheckComponent, |     CheckComponent, | ||||||
|  |     PasswordComponent, | ||||||
|     SaveViewConfigDialogComponent, |     SaveViewConfigDialogComponent, | ||||||
|     TagsComponent, |     TagsComponent, | ||||||
|     IfPermissionsDirective, |     IfPermissionsDirective, | ||||||
| @ -189,6 +193,8 @@ function initializeApp(settings: SettingsService) { | |||||||
|     UserEditDialogComponent, |     UserEditDialogComponent, | ||||||
|     GroupEditDialogComponent, |     GroupEditDialogComponent, | ||||||
|     PermissionsSelectComponent, |     PermissionsSelectComponent, | ||||||
|  |     MailAccountEditDialogComponent, | ||||||
|  |     MailRuleEditDialogComponent, | ||||||
|   ], |   ], | ||||||
|   imports: [ |   imports: [ | ||||||
|     BrowserModule, |     BrowserModule, | ||||||
|  | |||||||
| @ -17,7 +17,7 @@ | |||||||
|       </svg> |       </svg> | ||||||
|       <input class="form-control form-control-sm" type="text" placeholder="Search documents" aria-label="Search" |       <input class="form-control form-control-sm" type="text" placeholder="Search documents" aria-label="Search" | ||||||
|         [formControl]="searchField" [ngbTypeahead]="searchAutoComplete" (keyup)="searchFieldKeyup($event)" (selectItem)="itemSelected($event)" i18n-placeholder> |         [formControl]="searchField" [ngbTypeahead]="searchAutoComplete" (keyup)="searchFieldKeyup($event)" (selectItem)="itemSelected($event)" i18n-placeholder> | ||||||
|       <button *ngIf="!searchFieldEmpty" class="btn btn-link btn-sm px-0 position-absolute top-0 end-0" (click)="resetSearchField()"> |       <button type="button" *ngIf="!searchFieldEmpty" class="btn btn-link btn-sm px-0 position-absolute top-0 end-0" (click)="resetSearchField()"> | ||||||
|         <svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-x me-1" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> |         <svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-x me-1" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> | ||||||
|           <path fill-rule="evenodd" d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"/> |           <path fill-rule="evenodd" d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"/> | ||||||
|         </svg> |         </svg> | ||||||
| @ -177,13 +177,6 @@ | |||||||
|               </svg><span> <ng-container i18n>Settings</ng-container></span> |               </svg><span> <ng-container i18n>Settings</ng-container></span> | ||||||
|             </a> |             </a> | ||||||
|           </li> |           </li> | ||||||
|           <li class="nav-item" *ifPermissions="{ action: PermissionAction.View, type: PermissionType.Admin }" tourAnchor="tour.admin"> |  | ||||||
|             <a class="nav-link" href="admin/" ngbPopover="Admin" i18n-ngbPopover [disablePopover]="!slimSidebarEnabled" placement="end" container="body" triggers="mouseenter:mouseleave" popoverClass="popover-slim"> |  | ||||||
|               <svg class="sidebaricon" fill="currentColor"> |  | ||||||
|                 <use xlink:href="assets/bootstrap-icons.svg#toggles"/> |  | ||||||
|               </svg><span> <ng-container i18n>Admin</ng-container></span> |  | ||||||
|             </a> |  | ||||||
|           </li> |  | ||||||
|         </ul> |         </ul> | ||||||
| 
 | 
 | ||||||
|         <h6 class="sidebar-heading px-3 mt-auto pt-4 mb-1 text-muted"> |         <h6 class="sidebar-heading px-3 mt-auto pt-4 mb-1 text-muted"> | ||||||
| @ -191,7 +184,7 @@ | |||||||
|         </h6> |         </h6> | ||||||
|         <ul class="nav flex-column mb-2"> |         <ul class="nav flex-column mb-2"> | ||||||
|           <li class="nav-item" tourAnchor="tour.outro"> |           <li class="nav-item" tourAnchor="tour.outro"> | ||||||
|             <a class="nav-link" target="_blank" rel="noopener noreferrer" href="https://paperless-ngx.readthedocs.io/en/latest/" ngbPopover="Documentation" i18n-ngbPopover [disablePopover]="!slimSidebarEnabled" placement="end" container="body" triggers="mouseenter:mouseleave" popoverClass="popover-slim"> |             <a class="nav-link" target="_blank" rel="noopener noreferrer" href="https://docs.paperless-ngx.com" ngbPopover="Documentation" i18n-ngbPopover [disablePopover]="!slimSidebarEnabled" placement="end" container="body" triggers="mouseenter:mouseleave" popoverClass="popover-slim"> | ||||||
|               <svg class="sidebaricon" fill="currentColor"> |               <svg class="sidebaricon" fill="currentColor"> | ||||||
|                 <use xlink:href="assets/bootstrap-icons.svg#question-circle"/> |                 <use xlink:href="assets/bootstrap-icons.svg#question-circle"/> | ||||||
|               </svg><span> <ng-container i18n>Documentation</ng-container></span> |               </svg><span> <ng-container i18n>Documentation</ng-container></span> | ||||||
|  | |||||||
| @ -97,6 +97,15 @@ export class AppFrameComponent | |||||||
|     this.isMenuCollapsed = true |     this.isMenuCollapsed = true | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   get openDocuments(): PaperlessDocument[] { | ||||||
|  |     return this.openDocumentsService.getOpenDocuments() | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @HostListener('window:beforeunload') | ||||||
|  |   canDeactivate(): Observable<boolean> | boolean { | ||||||
|  |     return !this.openDocumentsService.hasDirty() | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   searchField = new FormControl('') |   searchField = new FormControl('') | ||||||
| 
 | 
 | ||||||
|   get searchFieldEmpty(): boolean { |   get searchFieldEmpty(): boolean { | ||||||
| @ -113,15 +122,6 @@ export class AppFrameComponent | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   get openDocuments(): PaperlessDocument[] { |  | ||||||
|     return this.openDocumentsService.getOpenDocuments() |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   @HostListener('window:beforeunload') |  | ||||||
|   canDeactivate(): Observable<boolean> | boolean { |  | ||||||
|     return !this.openDocumentsService.hasDirty() |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   searchAutoComplete = (text$: Observable<string>) => |   searchAutoComplete = (text$: Observable<string>) => | ||||||
|     text$.pipe( |     text$.pipe( | ||||||
|       debounceTime(200), |       debounceTime(200), | ||||||
|  | |||||||