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: | ||||
| 
 | ||||
|         - [The troubleshooting documentation](https://paperless-ngx.readthedocs.io/en/latest/troubleshooting.html). | ||||
|         - [The installation instructions](https://paperless-ngx.readthedocs.io/en/latest/setup.html#installation). | ||||
|         - [The troubleshooting documentation](https://docs.paperless-ngx.com/troubleshooting/). | ||||
|         - [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). | ||||
|         - Disable any customer container initialization scripts, if using any | ||||
| 
 | ||||
| @ -42,7 +42,15 @@ body: | ||||
|     id: logs | ||||
|     attributes: | ||||
|       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 | ||||
|   - type: input | ||||
|     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). | ||||
| - [ ] 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). | ||||
| - [ ] I have run all `pre-commit` hooks, see [documentation](https://paperless-ngx.readthedocs.io/en/latest/extending.html#code-formatting-with-pre-commit-hooks). | ||||
| - [ ] 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://docs.paperless-ngx.com/development/#code-formatting-with-pre-commit-hooks). | ||||
| - [ ] I have made corresponding changes to the documentation as needed. | ||||
| - [ ] I have checked my modifications for any breaking changes. | ||||
|  | ||||
							
								
								
									
										57
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						| @ -49,7 +49,7 @@ jobs: | ||||
|         name: Set up Python | ||||
|         uses: actions/setup-python@v4 | ||||
|         with: | ||||
|           python-version: 3.9 | ||||
|           python-version: 3.8 | ||||
|           cache: "pipenv" | ||||
|           cache-dependency-path: 'Pipfile.lock' | ||||
|       - | ||||
| @ -63,14 +63,32 @@ jobs: | ||||
|       - | ||||
|         name: Make documentation | ||||
|         run: | | ||||
|           cd docs/ | ||||
|           pipenv run make html | ||||
|           pipenv run mkdocs build --config-file ./mkdocs.yml | ||||
|       - | ||||
|         name: Upload artifact | ||||
|         uses: actions/upload-artifact@v3 | ||||
|         with: | ||||
|           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: | ||||
|     name: "Tests (${{ matrix.python-version }})" | ||||
| @ -81,15 +99,6 @@ jobs: | ||||
|       matrix: | ||||
|         python-version: ['3.8', '3.9', '3.10'] | ||||
|       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: | ||||
|       # Enable Tika end to end testing | ||||
|       TIKA_LIVE: 1 | ||||
| @ -97,12 +106,21 @@ jobs: | ||||
|       PAPERLESS_MAIL_TEST_HOST: ${{ secrets.TEST_MAIL_HOST }} | ||||
|       PAPERLESS_MAIL_TEST_USER: ${{ secrets.TEST_MAIL_USER }} | ||||
|       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: | ||||
|       - | ||||
|         name: Checkout | ||||
|         uses: actions/checkout@v3 | ||||
|         with: | ||||
|           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 | ||||
|         run: | | ||||
| @ -154,6 +172,12 @@ jobs: | ||||
|         run: | | ||||
|           cd src/ | ||||
|           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: | ||||
|     name: "Tests Frontend" | ||||
| @ -478,10 +502,9 @@ jobs: | ||||
|       - | ||||
|         name: Upload release archive | ||||
|         id: upload-release-asset | ||||
|         uses: actions/upload-release-asset@v1 | ||||
|         env: | ||||
|           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||
|         uses: shogo82148/actions-upload-release-asset@v1 | ||||
|         with: | ||||
|           github_token: ${{ secrets.GITHUB_TOKEN }} | ||||
|           upload_url: ${{ steps.create-release.outputs.upload_url }} | ||||
|           asset_path: ./paperless-ngx.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` | ||||
|           echo -e "$CURRENT_CHANGELOG" >> changelog-new.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.email "41898282+github-actions[bot]@users.noreply.github.com" | ||||
|           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: | ||||
| *.log | ||||
| 
 | ||||
| # Sphinx documentation | ||||
| docs/_build/ | ||||
| # MkDocs documentation | ||||
| site/ | ||||
| 
 | ||||
| # PyBuilder | ||||
| target/ | ||||
|  | ||||
| @ -11,13 +11,14 @@ repos: | ||||
|       - id: check-json | ||||
|         exclude: "tsconfig.*json" | ||||
|       - id: check-yaml | ||||
|         exclude: "charts/paperless-ngx/templates/common.yaml" | ||||
|       - id: check-toml | ||||
|       - id: check-executables-have-shebangs | ||||
|       - id: end-of-file-fixer | ||||
|         exclude_types: | ||||
|           - svg | ||||
|           - pofile | ||||
|         exclude: "(^LICENSE$)" | ||||
|         exclude: "^(LICENSE|charts/paperless-ngx/README.md)$" | ||||
|       - id: mixed-line-ending | ||||
|         args: | ||||
|           - "--fix=lf" | ||||
| @ -34,7 +35,7 @@ repos: | ||||
|           - javascript | ||||
|           - ts | ||||
|           - markdown | ||||
|         exclude: "(^Pipfile\\.lock$)" | ||||
|         exclude: "(^Pipfile\\.lock$)|(^charts/paperless-ngx/README.md$)" | ||||
|   # Python hooks | ||||
|   - repo: https://github.com/asottile/reorder_python_imports | ||||
|     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. | ||||
| 
 | ||||
| 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: | ||||
| 
 | ||||
| ... 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 | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										43
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						| @ -52,7 +52,7 @@ RUN set -eux \ | ||||
| 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.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.url="https://github.com/paperless-ngx/paperless-ngx" | ||||
| 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 | ||||
| ARG RUNTIME_PACKAGES="\ | ||||
|   # Python | ||||
|   python3 \ | ||||
|   python3-pip \ | ||||
|   python3-setuptools \ | ||||
|   # General utils | ||||
|   curl \ | ||||
|   file \ | ||||
|   # Docker specific | ||||
|   gosu \ | ||||
|   # Timezones support | ||||
|   tzdata \ | ||||
|   # fonts for text file thumbnail generation | ||||
|   fonts-liberation \ | ||||
|   gettext \ | ||||
|   ghostscript \ | ||||
|   gnupg \ | ||||
|   gosu \ | ||||
|   icc-profiles-free \ | ||||
|   imagemagick \ | ||||
|   media-types \ | ||||
|   # Image processing | ||||
|   liblept5 \ | ||||
|   libpq5 \ | ||||
|   libxml2 \ | ||||
|   liblcms2-2 \ | ||||
|   libtiff5 \ | ||||
|   libxslt1.1 \ | ||||
|   libfreetype6 \ | ||||
|   libwebp6 \ | ||||
|   libopenjp2-7 \ | ||||
|   libimagequant0 \ | ||||
|   libraqm0 \ | ||||
|   libgnutls30 \ | ||||
|   libjpeg62-turbo \ | ||||
|   python3 \ | ||||
|   python3-pip \ | ||||
|   python3-setuptools \ | ||||
|   # PostgreSQL | ||||
|   libpq5 \ | ||||
|   postgresql-client \ | ||||
|   # MySQL / MariaDB | ||||
|   mariadb-client \ | ||||
|   # For Numpy | ||||
|   libatlas3-base \ | ||||
| @ -110,17 +113,23 @@ ARG RUNTIME_PACKAGES="\ | ||||
|   tesseract-ocr-fra \ | ||||
|   tesseract-ocr-ita \ | ||||
|   tesseract-ocr-spa \ | ||||
|   # Suggested for OCRmyPDF | ||||
|   pngquant \ | ||||
|   # Suggested for pikepdf | ||||
|   jbig2dec \ | ||||
|   tzdata \ | ||||
|   unpaper \ | ||||
|   pngquant \ | ||||
|   # pikepdf / qpdf | ||||
|   jbig2dec \ | ||||
|   libxml2 \ | ||||
|   libxslt1.1 \ | ||||
|   libgnutls30 \ | ||||
|   # Mime type detection | ||||
|   file \ | ||||
|   libmagic1 \ | ||||
|   media-types \ | ||||
|   zlib1g \ | ||||
|   # Barcode splitter | ||||
|   libzbar0 \ | ||||
|   poppler-utils" | ||||
|   poppler-utils \ | ||||
|   # RapidFuzz on armv7 | ||||
|   libatomic1" | ||||
| 
 | ||||
| # Install basic runtime packages. | ||||
| # These change very infrequently | ||||
|  | ||||
							
								
								
									
										7
									
								
								Pipfile
									
									
									
									
									
								
							
							
						
						| @ -60,6 +60,9 @@ setproctitle = "*" | ||||
| nltk = "*" | ||||
| pdf2image = "*" | ||||
| flower = "*" | ||||
| bleach = "*" | ||||
| # https://www.piwheels.org/project/cryptography/ last built version | ||||
| cryptography = "==38.0.1" | ||||
| 
 | ||||
| [dev-packages] | ||||
| coveralls = "*" | ||||
| @ -71,10 +74,10 @@ pytest-django = "*" | ||||
| pytest-env = "*" | ||||
| pytest-sugar = "*" | ||||
| pytest-xdist = "*" | ||||
| sphinx = "~=5.3" | ||||
| sphinx_rtd_theme = "*" | ||||
| tox = "*" | ||||
| black = "*" | ||||
| pre-commit = "*" | ||||
| sphinx-autobuild = "*" | ||||
| myst-parser = "*" | ||||
| imagehash = "*" | ||||
| mkdocs-material = "*" | ||||
|  | ||||
							
								
								
									
										299
									
								
								Pipfile.lock
									
									
									
										generated
									
									
									
								
							
							
						
						| @ -1,7 +1,7 @@ | ||||
| { | ||||
|     "_meta": { | ||||
|         "hash": { | ||||
|             "sha256": "9fefc737155e789ced61b41750b4273c7780ac7801c50cf36dc5925be3b85783" | ||||
|             "sha256": "cbfe9920231de6e7f993962efb3cc371abdb6b08975232d4cf64d1bad1b53d7a" | ||||
|         }, | ||||
|         "pipfile-spec": 6, | ||||
|         "requires": {}, | ||||
| @ -99,6 +99,7 @@ | ||||
|                 "sha256:f04e857b59d9d1ccc39ce2da1021d196e47234873820cbeaad210724b1ee28ac", | ||||
|                 "sha256:fadbfe37f74051d024037f223b8e001611eac868b5c5b06144ef4d8b799862f2" | ||||
|             ], | ||||
|             "index": "pypi", | ||||
|             "markers": "python_version < '3.9'", | ||||
|             "version": "==0.2.1" | ||||
|         }, | ||||
| @ -109,6 +110,14 @@ | ||||
|             ], | ||||
|             "version": "==3.6.4.0" | ||||
|         }, | ||||
|         "bleach": { | ||||
|             "hashes": [ | ||||
|                 "sha256:085f7f33c15bd408dd9b17a4ad77c577db66d76203e5984b1bd59baeee948b2a", | ||||
|                 "sha256:0d03255c47eb9bd2f26aa9bb7f2107732e7e8fe195ca2f64709fcf3b0a4a085c" | ||||
|             ], | ||||
|             "index": "pypi", | ||||
|             "version": "==5.0.1" | ||||
|         }, | ||||
|         "celery": { | ||||
|             "extras": [ | ||||
|                 "redis" | ||||
| @ -1766,6 +1775,13 @@ | ||||
|             ], | ||||
|             "version": "==0.2.5" | ||||
|         }, | ||||
|         "webencodings": { | ||||
|             "hashes": [ | ||||
|                 "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", | ||||
|                 "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923" | ||||
|             ], | ||||
|             "version": "==0.5.1" | ||||
|         }, | ||||
|         "websockets": { | ||||
|             "hashes": [ | ||||
|                 "sha256:00213676a2e46b6ebf6045bc11d0f529d9120baa6f58d122b4021ad92adabd41", | ||||
| @ -2074,6 +2090,7 @@ | ||||
|             "version": "==0.4.6" | ||||
|         }, | ||||
|         "coverage": { | ||||
|             "extras": [], | ||||
|             "hashes": [ | ||||
|                 "sha256:027018943386e7b942fa832372ebc120155fd970837489896099f5cfa2890f79", | ||||
|                 "sha256:11b990d520ea75e7ee8dcab5bc908072aaada194a794db9f6d7d5cfd19661e5a", | ||||
| @ -2198,6 +2215,13 @@ | ||||
|             "index": "pypi", | ||||
|             "version": "==3.8.0" | ||||
|         }, | ||||
|         "ghp-import": { | ||||
|             "hashes": [ | ||||
|                 "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619", | ||||
|                 "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343" | ||||
|             ], | ||||
|             "version": "==2.1.0" | ||||
|         }, | ||||
|         "identify": { | ||||
|             "hashes": [ | ||||
|                 "sha256:48b7925fe122720088aeb7a6c34f17b27e706b72c61070f27fe3789094233440", | ||||
| @ -2214,6 +2238,14 @@ | ||||
|             "markers": "python_version >= '3.5'", | ||||
|             "version": "==3.4" | ||||
|         }, | ||||
|         "imagehash": { | ||||
|             "hashes": [ | ||||
|                 "sha256:5ad9a5cde14fe255745a8245677293ac0d67f09c330986a351f34b614ba62fb5", | ||||
|                 "sha256:7038d1b7f9e0585beb3dd8c0a956f02b95a346c0b5f24a9e8cc03ebadaf0aa70" | ||||
|             ], | ||||
|             "index": "pypi", | ||||
|             "version": "==4.3.1" | ||||
|         }, | ||||
|         "imagesize": { | ||||
|             "hashes": [ | ||||
|                 "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b", | ||||
| @ -2222,6 +2254,14 @@ | ||||
|             "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", | ||||
|             "version": "==1.4.1" | ||||
|         }, | ||||
|         "importlib-metadata": { | ||||
|             "hashes": [ | ||||
|                 "sha256:d5059f9f1e8e41f80e9c56c2ee58811450c31984dfa625329ffd7c0dad88a73b", | ||||
|                 "sha256:d84d17e21670ec07990e1044a99efe8d615d860fd176fc29ef5c306068fda313" | ||||
|             ], | ||||
|             "markers": "python_version < '3.10'", | ||||
|             "version": "==5.1.0" | ||||
|         }, | ||||
|         "iniconfig": { | ||||
|             "hashes": [ | ||||
|                 "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3", | ||||
| @ -2243,6 +2283,14 @@ | ||||
|             ], | ||||
|             "version": "==2.6.3" | ||||
|         }, | ||||
|         "markdown": { | ||||
|             "hashes": [ | ||||
|                 "sha256:cbb516f16218e643d8e0a95b309f77eb118cb138d39a4f27851e6a63581db874", | ||||
|                 "sha256:f5da449a6e1c989a4cea2631aa8ee67caa5a2ef855d551c88f9e309f4634c621" | ||||
|             ], | ||||
|             "markers": "python_version >= '3.6'", | ||||
|             "version": "==3.3.7" | ||||
|         }, | ||||
|         "markdown-it-py": { | ||||
|             "hashes": [ | ||||
|                 "sha256:93de681e5c021a432c63147656fe21790bc01231e0cd2da73626f1aa3ac0fe27", | ||||
| @ -2313,6 +2361,38 @@ | ||||
|             "markers": "python_version >= '3.7'", | ||||
|             "version": "==0.1.2" | ||||
|         }, | ||||
|         "mergedeep": { | ||||
|             "hashes": [ | ||||
|                 "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8", | ||||
|                 "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307" | ||||
|             ], | ||||
|             "markers": "python_version >= '3.6'", | ||||
|             "version": "==1.3.4" | ||||
|         }, | ||||
|         "mkdocs": { | ||||
|             "hashes": [ | ||||
|                 "sha256:8947af423a6d0facf41ea1195b8e1e8c85ad94ac95ae307fe11232e0424b11c5", | ||||
|                 "sha256:c8856a832c1e56702577023cd64cc5f84948280c1c0fcc6af4cd39006ea6aa8c" | ||||
|             ], | ||||
|             "markers": "python_version >= '3.7'", | ||||
|             "version": "==1.4.2" | ||||
|         }, | ||||
|         "mkdocs-material": { | ||||
|             "hashes": [ | ||||
|                 "sha256:b0ea0513fd8cab323e8a825d6692ea07fa83e917bb5db042e523afecc7064ab7", | ||||
|                 "sha256:c907b4b052240a5778074a30a78f31a1f8ff82d7012356dc26898b97559f082e" | ||||
|             ], | ||||
|             "index": "pypi", | ||||
|             "version": "==8.5.11" | ||||
|         }, | ||||
|         "mkdocs-material-extensions": { | ||||
|             "hashes": [ | ||||
|                 "sha256:9c003da71e2cc2493d910237448c672e00cefc800d3d6ae93d2fc69979e3bd93", | ||||
|                 "sha256:e41d9f38e4798b6617ad98ca8f7f1157b1e4385ac1459ca1e4ea219b556df945" | ||||
|             ], | ||||
|             "markers": "python_version >= '3.7'", | ||||
|             "version": "==1.1.1" | ||||
|         }, | ||||
|         "mypy-extensions": { | ||||
|             "hashes": [ | ||||
|                 "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d", | ||||
| @ -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'", | ||||
|             "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": { | ||||
|             "hashes": [ | ||||
|                 "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb", | ||||
| @ -2352,6 +2466,73 @@ | ||||
|             "markers": "python_version >= '3.7'", | ||||
|             "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": { | ||||
|             "hashes": [ | ||||
|                 "sha256:0cb405749187a194f444c25c82ef7225232f11564721eabffc6ec70df83b11cb", | ||||
| @ -2400,6 +2581,14 @@ | ||||
|             "markers": "python_version >= '3.6'", | ||||
|             "version": "==2.13.0" | ||||
|         }, | ||||
|         "pymdown-extensions": { | ||||
|             "hashes": [ | ||||
|                 "sha256:0f8fb7b74a37a61cc34e90b2c91865458b713ec774894ffad64353a5fce85cfc", | ||||
|                 "sha256:ac698c15265680db5eb13cd4342abfcde2079ac01e5486028f47a1b41547b859" | ||||
|             ], | ||||
|             "markers": "python_version >= '3.7'", | ||||
|             "version": "==9.9" | ||||
|         }, | ||||
|         "pyparsing": { | ||||
|             "hashes": [ | ||||
|                 "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb", | ||||
| @ -2471,6 +2660,37 @@ | ||||
|             ], | ||||
|             "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": { | ||||
|             "hashes": [ | ||||
|                 "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf", | ||||
| @ -2516,6 +2736,14 @@ | ||||
|             ], | ||||
|             "version": "==6.0" | ||||
|         }, | ||||
|         "pyyaml-env-tag": { | ||||
|             "hashes": [ | ||||
|                 "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb", | ||||
|                 "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069" | ||||
|             ], | ||||
|             "markers": "python_version >= '3.6'", | ||||
|             "version": "==0.1" | ||||
|         }, | ||||
|         "requests": { | ||||
|             "hashes": [ | ||||
|                 "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983", | ||||
| @ -2524,6 +2752,35 @@ | ||||
|             "markers": "python_version >= '3.7' and python_version < '4'", | ||||
|             "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": { | ||||
|             "hashes": [ | ||||
|                 "sha256:d0b9a8433464d5800cbe05094acf5c6d52a91bfac9b52bcfc4d41382be5d5d31", | ||||
| @ -2552,7 +2809,6 @@ | ||||
|                 "sha256:060ca5c9f7ba57a08a1219e547b269fadf125ae25b06b9fa7f66768efb652d6d", | ||||
|                 "sha256:51026de0a9ff9fc13c05d74913ad66047e104f56a129ff73e174eb5c3ee794b5" | ||||
|             ], | ||||
|             "index": "pypi", | ||||
|             "version": "==5.3.0" | ||||
|         }, | ||||
|         "sphinx-autobuild": { | ||||
| @ -2691,6 +2947,45 @@ | ||||
|             ], | ||||
|             "markers": "python_version >= '3.6'", | ||||
|             "version": "==20.16.6" | ||||
|         }, | ||||
|         "watchdog": { | ||||
|             "hashes": [ | ||||
|                 "sha256:083171652584e1b8829581f965b9b7723ca5f9a2cd7e20271edf264cfd7c1412", | ||||
|                 "sha256:117ffc6ec261639a0209a3252546b12800670d4bf5f84fbd355957a0595fe654", | ||||
|                 "sha256:186f6c55abc5e03872ae14c2f294a153ec7292f807af99f57611acc8caa75306", | ||||
|                 "sha256:195fc70c6e41237362ba720e9aaf394f8178bfc7fa68207f112d108edef1af33", | ||||
|                 "sha256:226b3c6c468ce72051a4c15a4cc2ef317c32590d82ba0b330403cafd98a62cfd", | ||||
|                 "sha256:247dcf1df956daa24828bfea5a138d0e7a7c98b1a47cf1fa5b0c3c16241fcbb7", | ||||
|                 "sha256:255bb5758f7e89b1a13c05a5bceccec2219f8995a3a4c4d6968fe1de6a3b2892", | ||||
|                 "sha256:43ce20ebb36a51f21fa376f76d1d4692452b2527ccd601950d69ed36b9e21609", | ||||
|                 "sha256:4f4e1c4aa54fb86316a62a87b3378c025e228178d55481d30d857c6c438897d6", | ||||
|                 "sha256:5952135968519e2447a01875a6f5fc8c03190b24d14ee52b0f4b1682259520b1", | ||||
|                 "sha256:64a27aed691408a6abd83394b38503e8176f69031ca25d64131d8d640a307591", | ||||
|                 "sha256:6b17d302850c8d412784d9246cfe8d7e3af6bcd45f958abb2d08a6f8bedf695d", | ||||
|                 "sha256:70af927aa1613ded6a68089a9262a009fbdf819f46d09c1a908d4b36e1ba2b2d", | ||||
|                 "sha256:7a833211f49143c3d336729b0020ffd1274078e94b0ae42e22f596999f50279c", | ||||
|                 "sha256:8250546a98388cbc00c3ee3cc5cf96799b5a595270dfcfa855491a64b86ef8c3", | ||||
|                 "sha256:97f9752208f5154e9e7b76acc8c4f5a58801b338de2af14e7e181ee3b28a5d39", | ||||
|                 "sha256:9f05a5f7c12452f6a27203f76779ae3f46fa30f1dd833037ea8cbc2887c60213", | ||||
|                 "sha256:a735a990a1095f75ca4f36ea2ef2752c99e6ee997c46b0de507ba40a09bf7330", | ||||
|                 "sha256:ad576a565260d8f99d97f2e64b0f97a48228317095908568a9d5c786c829d428", | ||||
|                 "sha256:b530ae007a5f5d50b7fbba96634c7ee21abec70dc3e7f0233339c81943848dc1", | ||||
|                 "sha256:bfc4d351e6348d6ec51df007432e6fe80adb53fd41183716017026af03427846", | ||||
|                 "sha256:d3dda00aca282b26194bdd0adec21e4c21e916956d972369359ba63ade616153", | ||||
|                 "sha256:d9820fe47c20c13e3c9dd544d3706a2a26c02b2b43c993b62fcd8011bcc0adb3", | ||||
|                 "sha256:ed80a1628cee19f5cfc6bb74e173f1b4189eb532e705e2a13e3250312a62e0c9", | ||||
|                 "sha256:ee3e38a6cc050a8830089f79cbec8a3878ec2fe5160cdb2dc8ccb6def8552658" | ||||
|             ], | ||||
|             "index": "pypi", | ||||
|             "version": "==2.1.9" | ||||
|         }, | ||||
|         "zipp": { | ||||
|             "hashes": [ | ||||
|                 "sha256:4fcb6f278987a6605757302a6e40e896257570d11c51628968ccb2a47e80c6c1", | ||||
|                 "sha256:7a7262fd930bd3e36c50b9a64897aec3fafff3dfdeec9623ae22b40e93f99bb8" | ||||
|             ], | ||||
|             "markers": "python_version < '3.9'", | ||||
|             "version": "==3.10.0" | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
							
								
								
									
										22
									
								
								README.md
									
									
									
									
									
								
							
							
						
						| @ -1,8 +1,9 @@ | ||||
| [](https://github.com/paperless-ngx/paperless-ngx/actions) | ||||
| [](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://matrix.to/#/#paperless:adnidor.de) | ||||
| [](https://matrix.to/#/%23paperlessngx%3Amatrix.org) | ||||
| [](https://demo.paperless-ngx.com) | ||||
| 
 | ||||
| <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%" /> | ||||
| @ -32,13 +33,13 @@ A demo is available at [demo.paperless-ngx.com](https://demo.paperless-ngx.com) | ||||
| 
 | ||||
| # Features | ||||
| 
 | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| 
 | ||||
| - 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. | ||||
| - 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. | ||||
| - Single page application front end. | ||||
|   - 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. | ||||
| - 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. | ||||
| - [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 | ||||
| 
 | ||||
| @ -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)" | ||||
| ``` | ||||
| 
 | ||||
| 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 --> | ||||
| 
 | ||||
| ### 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 | ||||
| 
 | ||||
| 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 | ||||
| 
 | ||||
| @ -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 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. | ||||
| - [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. | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										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_DBENGINE: mariadb | ||||
|       PAPERLESS_DBHOST: db | ||||
|       PAPERLESS_DBUSER: paperless | ||||
|       PAPERLESS_DBPASSWORD: paperless | ||||
|       PAPERLESS_DBUSER: paperless # only needed if non-default username | ||||
|       PAPERLESS_DBPASS: paperless # only needed if non-default password | ||||
|       PAPERLESS_DBPORT: 3306 | ||||
|       PAPERLESS_TIKA_ENABLED: 1 | ||||
|       PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000 | ||||
| @ -87,9 +87,12 @@ services: | ||||
|   gotenberg: | ||||
|     image: docker.io/gotenberg/gotenberg:7.6 | ||||
|     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-routes=true" | ||||
|       - "--chromium-disable-javascript=true" | ||||
|       - "--chromium-allow-list=file:///tmp/.*" | ||||
| 
 | ||||
|   tika: | ||||
|     image: ghcr.io/paperless-ngx/tika:latest | ||||
|  | ||||
| @ -71,8 +71,8 @@ services: | ||||
|       PAPERLESS_REDIS: redis://broker:6379 | ||||
|       PAPERLESS_DBENGINE: mariadb | ||||
|       PAPERLESS_DBHOST: db | ||||
|       PAPERLESS_DBUSER: paperless | ||||
|       PAPERLESS_DBPASSWORD: paperless | ||||
|       PAPERLESS_DBUSER: paperless # only needed if non-default username | ||||
|       PAPERLESS_DBPASS: paperless # only needed if non-default password | ||||
|       PAPERLESS_DBPORT: 3306 | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -79,9 +79,13 @@ services: | ||||
|   gotenberg: | ||||
|     image: docker.io/gotenberg/gotenberg:7.6 | ||||
|     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-routes=true" | ||||
|       - "--chromium-disable-javascript=true" | ||||
|       - "--chromium-allow-list=file:///tmp/.*" | ||||
| 
 | ||||
|   tika: | ||||
|     image: ghcr.io/paperless-ngx/tika:latest | ||||
|  | ||||
| @ -67,9 +67,13 @@ services: | ||||
|   gotenberg: | ||||
|     image: docker.io/gotenberg/gotenberg:7.6 | ||||
|     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-routes=true" | ||||
|       - "--chromium-disable-javascript=true" | ||||
|       - "--chromium-allow-list=file:///tmp/.*" | ||||
| 
 | ||||
|   tika: | ||||
|     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() { | ||||
| 
 | ||||
| 	# Setup environment from secrets before anything else | ||||
| @ -132,13 +172,16 @@ initialize() { | ||||
| 	set -e | ||||
| 
 | ||||
| 	"${gosu_cmd[@]}" /sbin/docker-prepare.sh | ||||
| 
 | ||||
| 	# Leave this last thing | ||||
| 	custom_container_init | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| install_languages() { | ||||
| 	echo "Installing languages..." | ||||
| 
 | ||||
| 	local -r langs="$1" | ||||
| 	read -ra langs <<<"$langs" | ||||
| 	read -ra langs <<<"$1" | ||||
| 
 | ||||
| 	# Check that it is not empty | ||||
| 	if [ ${#langs[@]} -eq 0 ]; then | ||||
|  | ||||
| @ -89,46 +89,6 @@ superuser() { | ||||
| 	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() { | ||||
| 	if [[ "${PAPERLESS_DBENGINE}" == "mariadb" ]]; then | ||||
| 		wait_for_mariadb | ||||
| @ -144,9 +104,6 @@ do_work() { | ||||
| 
 | ||||
| 	superuser | ||||
| 
 | ||||
| 	# Leave this last thing | ||||
| 	custom_container_init | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 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 | ||||
| 
 | ||||
| ## 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 | ||||
| 
 | ||||
| ### Notes | ||||
| 
 | ||||
| - Version 1.9.1 incorrectly displays the version string as 1.9.0 | ||||
| 
 | ||||
| ### Bug Fixes | ||||
| 
 | ||||
| - 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 | ||||
|   [\@jonasc](https://github.com/jonasc) ([\#270](https://github.com/paperless-ngx/paperless-ngx/pull/270)) | ||||
| - Global drag\'n\'drop [\@shamoon](https://github.com/shamoon) | ||||
| - Global drag'n'drop [\@shamoon](https://github.com/shamoon) | ||||
|   ([\#283](https://github.com/paperless-ngx/paperless-ngx/pull/283)) | ||||
| - Fix: download buttons should disable while waiting | ||||
|   [\@shamoon](https://github.com/shamoon) ([\#630](https://github.com/paperless-ngx/paperless-ngx/pull/630)) | ||||
| @ -425,7 +648,7 @@ | ||||
| 
 | ||||
| ### Bug Fixes | ||||
| 
 | ||||
| - Add \"localhost\" to ALLOWED_HOSTS | ||||
| - Add "localhost" to ALLOWED_HOSTS | ||||
|   [\@gador](https://github.com/gador) ([\#700](https://github.com/paperless-ngx/paperless-ngx/pull/700)) | ||||
| - Fix: scanners table [\@qcasey](https://github.com/qcasey) ([\#690](https://github.com/paperless-ngx/paperless-ngx/pull/690)) | ||||
| - Adds wait for file before consuming | ||||
| @ -462,7 +685,7 @@ | ||||
|   ([\#393](https://github.com/paperless-ngx/paperless-ngx/pull/393)) | ||||
| - Fix filterable dropdown buttons arent translated | ||||
|   [\@shamoon](https://github.com/shamoon) ([\#366](https://github.com/paperless-ngx/paperless-ngx/pull/366)) | ||||
| - Fix 224: \"Auto-detected date is day before receipt date\" | ||||
| - Fix 224: "Auto-detected date is day before receipt date" | ||||
|   [\@a17t](https://github.com/a17t) ([\#246](https://github.com/paperless-ngx/paperless-ngx/pull/246)) | ||||
| - Fix minor sphinx errors [\@shamoon](https://github.com/shamoon) | ||||
|   ([\#322](https://github.com/paperless-ngx/paperless-ngx/pull/322)) | ||||
| @ -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 | ||||
| excellent teamwork! | ||||
| 
 | ||||
| Version 1.6.0 merges several pending PRs from jonaswinkler\'s repo and | ||||
| Version 1.6.0 merges several pending PRs from jonaswinkler's repo and | ||||
| includes new feature updates and bug fixes. Major backend and UI changes | ||||
| include: | ||||
| 
 | ||||
| @ -544,14 +767,14 @@ include: | ||||
|   when document list is reloading ([jonaswinkler\#1297](https://github.com/jonaswinkler/paperless-ng/pull/1297)). | ||||
| - [\@shamoon](https://github.com/shamoon) improved the PDF viewer on | ||||
|   mobile ([\#2](https://github.com/paperless-ngx/paperless-ngx/pull/2)). | ||||
| - [\@shamoon](https://github.com/shamoon) added \'any\' / \'all\' and | ||||
|   \'not\' filtering with tags ([\#10](https://github.com/paperless-ngx/paperless-ngx/pull/10)). | ||||
| - [\@shamoon](https://github.com/shamoon) added 'any' / 'all' and | ||||
|   'not' filtering with tags ([\#10](https://github.com/paperless-ngx/paperless-ngx/pull/10)). | ||||
| - [\@shamoon](https://github.com/shamoon) added warnings for unsaved | ||||
|   changes, with smart edit buttons ([\#13](https://github.com/paperless-ngx/paperless-ngx/pull/13)). | ||||
| - [\@benjaminfrank](https://github.com/benjaminfrank) enabled a | ||||
|   non-root access to port 80 via systemd ([\#18](https://github.com/paperless-ngx/paperless-ngx/pull/18)). | ||||
| - [\@tribut](https://github.com/tribut) added simple \"delete to | ||||
|   trash\" functionality ([\#24](https://github.com/paperless-ngx/paperless-ngx/pull/24)). See `PAPERLESS_TRASH_DIR`. | ||||
| - [\@tribut](https://github.com/tribut) added simple "delete to | ||||
|   trash" functionality ([\#24](https://github.com/paperless-ngx/paperless-ngx/pull/24)). See `PAPERLESS_TRASH_DIR`. | ||||
| - [\@amenk](https://github.com/amenk) fixed the search box overlay | ||||
|   menu on mobile ([\#32](https://github.com/paperless-ngx/paperless-ngx/pull/32)). | ||||
| - [\@dblitt](https://github.com/dblitt) updated the login form to not | ||||
| @ -727,26 +950,22 @@ This is a maintenance release. | ||||
| - Changes | ||||
|   - Firefox only: Highlight search query in PDF previews. | ||||
|   - New URL pattern for accessing documents by ASN directly | ||||
|     (<http://>\<paperless\>/asn/123) | ||||
|     (<http://><paperless>/asn/123) | ||||
|   - Added logging when executing pre\* and post-consume scripts. | ||||
|   - Better error logging during document consumption. | ||||
|   - Updated python dependencies. | ||||
|   - Automatically inserts typed text when opening \"Create new\" | ||||
|   - Automatically inserts typed text when opening "Create new" | ||||
|     dialogs on the document details page. | ||||
| - Fixes | ||||
|   - Fixed an issue with null characters in the document content. | ||||
| 
 | ||||
| ::: {.note} | ||||
| ::: {.title} | ||||
| Note | ||||
| ::: | ||||
| !!! note | ||||
| 
 | ||||
| The changed to the full text searching require you to reindex your | ||||
| documents. _The docker image does this automatically, you don\'t need to | ||||
| documents. _The docker image does this automatically, you don't need to | ||||
| do anything._ To do this, execute the `document_index reindex` | ||||
| management command (see `administration-index`{.interpreted-text | ||||
| role="ref"}). | ||||
| ::: | ||||
| 
 | ||||
| ### paperless-ng 1.3.2 | ||||
| 
 | ||||
| @ -849,7 +1068,7 @@ This release contains new database migrations. | ||||
|   worker processes of the web server. See | ||||
|   `configuration-docker`{.interpreted-text role="ref"}. | ||||
| - Some more memory usage optimizations. | ||||
| - Don\'t show inbox statistics if no inbox tag is defined. | ||||
| - Don't show inbox statistics if no inbox tag is defined. | ||||
| 
 | ||||
| ### paperless-ng 1.1.2 | ||||
| 
 | ||||
| @ -869,8 +1088,8 @@ This release contains new database migrations. | ||||
| 
 | ||||
| This release contains new database migrations. | ||||
| 
 | ||||
| - Fixed a bug in the sanity checker that would cause it to display \"x | ||||
|   not in list\" errors instead of actual issues. | ||||
| - Fixed a bug in the sanity checker that would cause it to display "x | ||||
|   not in list" errors instead of actual issues. | ||||
| - Fixed a bug with filename generation for archive filenames that | ||||
|   would cause the archive files of two documents to overlap. | ||||
|   - This happened when `PAPERLESS_FILENAME_FORMAT` is used and the | ||||
| @ -879,8 +1098,8 @@ This release contains new database migrations. | ||||
|   - Paperless will now store the archive filename in the database as | ||||
|     well instead of deriving it from the original filename, and use | ||||
|     the same logic for detecting and avoiding filename clashes | ||||
|     that\'s also used for original filenames. | ||||
|   - The migrations will repair any missing archive files. If you\'re | ||||
|     that's also used for original filenames. | ||||
|   - The migrations will repair any missing archive files. If you're | ||||
|     using tika, ensure that tika is running while performing the | ||||
|     migration. Docker-compose will take care of that. | ||||
| - Fixed a bug with thumbnail regeneration when TIKA integration was | ||||
| @ -888,8 +1107,8 @@ This release contains new database migrations. | ||||
| - Added ASN as a placeholder field to the filename format. | ||||
| - The docker image now comes with built-in shortcuts for most | ||||
|   management commands. These are now the recommended way to execute | ||||
|   management commands, since these also ensure that they\'re always | ||||
|   executed as the paperless user and you\'re less likely to run into | ||||
|   management commands, since these also ensure that they're always | ||||
|   executed as the paperless user and you're less likely to run into | ||||
|   permission issues. See | ||||
|   `utilities-management-commands`{.interpreted-text role="ref"}. | ||||
| 
 | ||||
| @ -911,10 +1130,7 @@ This release contains new database migrations. | ||||
| - Live updates to document lists and saved views when new documents | ||||
|   are added. | ||||
| 
 | ||||
|   ::: {.hint} | ||||
|   ::: {.title} | ||||
|   Hint | ||||
|   ::: | ||||
|   !!! tip | ||||
| 
 | ||||
|   For status notifications and live updates to work, paperless now | ||||
|   requires an [ASGI](https://asgi.readthedocs.io/en/latest/)-enabled | ||||
| @ -937,7 +1153,6 @@ This release contains new database migrations. | ||||
| 
 | ||||
|   Apache `mod_wsgi` users, see | ||||
|   `this note <faq-mod_wsgi>`{.interpreted-text role="ref"}. | ||||
|   ::: | ||||
| 
 | ||||
| - Paperless now offers suggestions for tags, correspondents and types | ||||
|   on the document detail page. | ||||
| @ -961,8 +1176,8 @@ This release contains new database migrations. | ||||
|   - Better icon for document previews. | ||||
|   - Better info section in the side bar. | ||||
|   - Paperless no longer logs to the database. Instead, logs are | ||||
|     written to rotating log files. This solves many \"database is | ||||
|     locked\" issues on Raspberry Pi, especially when SQLite is used. | ||||
|     written to rotating log files. This solves many "database is | ||||
|     locked" issues on Raspberry Pi, especially when SQLite is used. | ||||
|   - By default, log files are written to `PAPERLESS_DATA_DIR/log/`. | ||||
|     Logging settings can be adjusted with `PAPERLESS_LOGGING_DIR`, | ||||
|     `PAPERLESS_LOGROTATE_MAX_SIZE` and | ||||
| @ -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 | ||||
|     document list. | ||||
|   - Filtering correspondent, type and tag management pages by name. | ||||
|   - Focus \"Name\" field in dialogs by default. | ||||
|   - Focus "Name" field in dialogs by default. | ||||
| 
 | ||||
| ### paperless-ng 0.9.14 | ||||
| 
 | ||||
| @ -1053,8 +1268,8 @@ paperless. | ||||
|   - Fixed an issue with filenames of downloaded files: Dates where | ||||
|     off by one day due to timezone issues. | ||||
|   - Searching will continue to work even when the index returns | ||||
|     non-existing documents. This resulted in \"Document does not | ||||
|     exist\" errors before. Instead, a warning is logged, indicating | ||||
|     non-existing documents. This resulted in "Document does not | ||||
|     exist" errors before. Instead, a warning is logged, indicating | ||||
|     the issue. | ||||
|   - An issue with the consumer crashing when invalid regular | ||||
|     expression were used was fixed. | ||||
| @ -1095,11 +1310,11 @@ paperless. | ||||
|     new ASN to a document. | ||||
|   - Form field validation: When providing invalid input in a form | ||||
|     (such as a duplicate ASN or no name), paperless now has visual | ||||
|     indicators and clearer error messages about what\'s wrong. | ||||
|     indicators and clearer error messages about what's wrong. | ||||
|   - Paperless disables buttons with network actions (such as save | ||||
|     and delete) when a network action is active. This indicates that | ||||
|     something is happening and prevents double clicking. | ||||
|   - When using \"Save & next\", the title field is focussed | ||||
|   - When using "Save & next", the title field is focussed | ||||
|     automatically to better support keyboard editing. | ||||
|   - E-Mail: Added filter rule parameters to allow inline attachments | ||||
|     (watch out for mails with inlined images!) and attachment | ||||
| @ -1108,11 +1323,11 @@ paperless. | ||||
|     Shamoon](https://github.com/shamoon). This is useful for hiding | ||||
|     Paperless behind single sign on applications such as | ||||
|     [authelia](https://www.authelia.com/). | ||||
|   - \"Clear filters\" has been renamed to \"Reset filters\" and now | ||||
|   - "Clear filters" has been renamed to "Reset filters" and now | ||||
|     correctly restores the default filters on saved views. Thanks to | ||||
|     [Michael Shamoon](https://github.com/shamoon) | ||||
| - Fixes | ||||
|   - Paperless was unable to save views when \"Not assigned\" was | ||||
|   - Paperless was unable to save views when "Not assigned" was | ||||
|     chosen in one of the filter dropdowns. | ||||
|   - Clearer error messages when pre and post consumption scripts do | ||||
|     not exist. | ||||
| @ -1128,7 +1343,7 @@ paperless. | ||||
| ### paperless-ng 0.9.10 | ||||
| 
 | ||||
| - Bulk editing | ||||
|   - Thanks to [Michael Shamoon](https://github.com/shamoon), we\'ve | ||||
|   - Thanks to [Michael Shamoon](https://github.com/shamoon), we've | ||||
|     got a new interface for the bulk editor. | ||||
|   - There are some configuration options in the settings to alter | ||||
|     the behavior. | ||||
| @ -1137,7 +1352,7 @@ paperless. | ||||
|     publishes a webmanifest, which is useful for adding the | ||||
|     application to home screens on mobile devices. | ||||
|   - The Paperless-ng logo now navigates to the dashboard. | ||||
|   - Filter for documents that don\'t have any correspondents, types | ||||
|   - Filter for documents that don't have any correspondents, types | ||||
|     or tags assigned. | ||||
|   - Tags, types and correspondents are now sorted case insensitive. | ||||
|   - Lots of preparation work for localization support. | ||||
| @ -1151,10 +1366,7 @@ paperless. | ||||
|   - The consumer used to stop working when encountering an | ||||
|     incomplete classifier model file. | ||||
| 
 | ||||
| ::: {.note} | ||||
| ::: {.title} | ||||
| Note | ||||
| ::: | ||||
| !!! note | ||||
| 
 | ||||
| The bulk delete operations did not update the search index. Therefore, | ||||
| documents that you deleted remained in the index and caused the search | ||||
| @ -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 | ||||
| `running the management command document_index with the argument reindex <administration-index>`{.interpreted-text | ||||
| role="ref"}. | ||||
| ::: | ||||
| 
 | ||||
| ### paperless-ng 0.9.9 | ||||
| 
 | ||||
| @ -1176,18 +1387,18 @@ Christmas release! | ||||
|   - The following operations are available: Add and remove | ||||
|     correspondents, tags, document types from selected documents, as | ||||
|     well as mass-deleting documents. | ||||
|   - We\'ve got a more fancy UI in the works that makes these | ||||
|     features more accessible, but that\'s not quite ready yet. | ||||
|   - We've got a more fancy UI in the works that makes these | ||||
|     features more accessible, but that's not quite ready yet. | ||||
| - Searching | ||||
|   - Paperless now supports searching for similar documents (\"More | ||||
|     like this\") both from the document detail page as well as from | ||||
|   - Paperless now supports searching for similar documents ("More | ||||
|     like this") both from the document detail page as well as from | ||||
|     individual search results. | ||||
|   - A search score indicates how well a document matches the search | ||||
|     query, or how similar a document is to a given reference | ||||
|     document. | ||||
| - Other additions and changes | ||||
|   - Clarification in the UI that the fields \"Match\" and \"Is | ||||
|     insensitive\" are not relevant for the Auto matching algorithm. | ||||
|   - Clarification in the UI that the fields "Match" and "Is | ||||
|     insensitive" are not relevant for the Auto matching algorithm. | ||||
|   - New select interface for tags, types and correspondents allows | ||||
|     filtering. This also improves tag selection. Thanks again to | ||||
|     [Michael Shamoon](https://github.com/shamoon)! | ||||
| @ -1268,11 +1479,11 @@ This release focusses primarily on many small issues with the UI. | ||||
|   - Paperless now has proper window titles. | ||||
|   - Fixed an issue with the small cards when more than 7 tags were | ||||
|     used. | ||||
|   - Navigation of the \"Show all\" links adjusted. They navigate to | ||||
|   - Navigation of the "Show all" links adjusted. They navigate to | ||||
|     the saved view now, if available in the sidebar. | ||||
|   - Some indication on the document lists that a filter is active | ||||
|     was added. | ||||
|   - There\'s a new filter to filter for documents that do _not_ have | ||||
|   - There's a new filter to filter for documents that do _not_ have | ||||
|     a certain tag. | ||||
|   - The file upload box now shows upload progress. | ||||
|   - The document edit page was reorganized. | ||||
| @ -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 | ||||
|     it detects duplicate filenames. | ||||
| 
 | ||||
| ::: {.note} | ||||
| ::: {.title} | ||||
| Note | ||||
| ::: | ||||
| !!! note | ||||
| 
 | ||||
| The changes to the filename format will apply to newly added documents | ||||
| and changed documents. If you want all files to reflect these changes, | ||||
| execute the `document_renamer` management command. | ||||
| ::: | ||||
| 
 | ||||
| ### paperless-ng 0.9.5 | ||||
| 
 | ||||
| @ -1388,7 +1595,7 @@ primarily. | ||||
|     need to do this once, since the schema of the search index | ||||
|     changed. Paperless keeps the index updated after that whenever | ||||
|     something changes. | ||||
|   - Paperless now has spelling corrections (\"Did you mean\") for | ||||
|   - Paperless now has spelling corrections ("Did you mean") for | ||||
|     miss-typed queries. | ||||
|   - The documentation contains | ||||
|     `information about the query syntax <basic-searching>`{.interpreted-text | ||||
| @ -1458,7 +1665,7 @@ primarily. | ||||
|   role="ref"} This features will most likely be removed in future | ||||
|   versions. | ||||
| - **Added:** New frontend. Features: | ||||
|   - Single page application: It\'s much more responsive than the | ||||
|   - Single page application: It's much more responsive than the | ||||
|     django admin pages. | ||||
|   - Dashboard. Shows recently scanned documents, or todo notes, or | ||||
|     other documents at wish. Allows uploading of documents. Shows | ||||
| @ -1480,7 +1687,7 @@ primarily. | ||||
| - **Added:** Archive serial numbers. Assign these to quickly find | ||||
|   documents stored in physical binders. | ||||
| - **Added:** Enabled the internal user management of django. This | ||||
|   isn\'t really a multi user solution, however, it allows more than | ||||
|   isn't really a multi user solution, however, it allows more than | ||||
|   one user to access the website and set some basic permissions / | ||||
|   renew passwords. | ||||
| - **Modified \[breaking\]:** All new mail consumer with customizable | ||||
| @ -1535,7 +1742,7 @@ primarily. | ||||
| - **Settings:** | ||||
|   - `PAPERLESS_FORGIVING_OCR` is now default and gone. Reason: Even | ||||
|     if `langdetect` fails to detect a language, tesseract still does | ||||
|     a very good job at ocr\'ing a document with the default | ||||
|     a very good job at ocr'ing a document with the default | ||||
|     language. Certain language specifics such as umlauts may not get | ||||
|     picked up properly. | ||||
|   - `PAPERLESS_DEBUG` defaults to `false`. | ||||
| @ -1616,34 +1823,34 @@ primarily. | ||||
|   [\#442](https://github.com/the-paperless-project/paperless/pull/442). | ||||
| - Added a `.editorconfig` file to better specify coding style. | ||||
| - [Joshua Taillon](https://github.com/jat255) also added some logic to | ||||
|   tie Paperless\' date guessing logic into how it parses file names on | ||||
|   tie Paperless' date guessing logic into how it parses file names on | ||||
|   import. | ||||
|   [\#440](https://github.com/the-paperless-project/paperless/pull/440) | ||||
| 
 | ||||
| ### 2.5.0 | ||||
| 
 | ||||
| - **New dependency**: Paperless now optimises thumbnail generation | ||||
|   with [optipng](http://optipng.sourceforge.net/), so you\'ll need to | ||||
|   with [optipng](http://optipng.sourceforge.net/), so you'll need to | ||||
|   install that somewhere in your PATH or declare its location in | ||||
|   `PAPERLESS_OPTIPNG_BINARY`. The Docker image has already been | ||||
|   updated on the Docker Hub, so you just need to pull the latest one | ||||
|   from there if you\'re a Docker user. | ||||
| - \"Login free\" instances of Paperless were breaking whenever you | ||||
|   from there if you're a Docker user. | ||||
| - "Login free" instances of Paperless were breaking whenever you | ||||
|   tried to edit objects in the admin: adding/deleting tags or | ||||
|   correspondents, or even fixing spelling. This was due to the \"user | ||||
|   hack\" we were applying to sessions that weren\'t using a login, as | ||||
|   that hack user didn\'t have a valid id. The fix was to attribute the | ||||
|   correspondents, or even fixing spelling. This was due to the "user | ||||
|   hack" we were applying to sessions that weren't using a login, as | ||||
|   that hack user didn't have a valid id. The fix was to attribute the | ||||
|   first user id in the system to this hack user. | ||||
|   [\#394](https://github.com/the-paperless-project/paperless/issues/394) | ||||
| - A problem in how we handle slug values on Tags and Correspondents | ||||
|   required a few changes to how we handle this field | ||||
|   [\#393](https://github.com/the-paperless-project/paperless/issues/393): | ||||
|   1.  Slugs are no longer editable. They\'re derived from the name of | ||||
|   1.  Slugs are no longer editable. They're derived from the name of | ||||
|       the tag or correspondent at save time, so if you wanna change | ||||
|       the slug, you have to change the name, and even then you\'re | ||||
|       the slug, you have to change the name, and even then you're | ||||
|       restricted to the rules of the `slugify()` function. The slug | ||||
|       value is still visible in the admin though. | ||||
|   2.  I\'ve added a migration to go over all existing tags & | ||||
|   2.  I've added a migration to go over all existing tags & | ||||
|       correspondents and rewrite the `.slug` values to ones conforming | ||||
|       to the `slugify()` rules. | ||||
|   3.  The consumption process now uses the same rules as `.save()` in | ||||
| @ -1654,7 +1861,7 @@ primarily. | ||||
|   Thanks to [Andrew Peng](https://github.com/pengc99) for reporting | ||||
|   this. | ||||
|   [\#414](https://github.com/the-paperless-project/paperless/issues/414). | ||||
| - A bug in the Dockerfile meant that Tesseract language files weren\'t | ||||
| - A bug in the Dockerfile meant that Tesseract language files weren't | ||||
|   being installed correctly. [euri10](https://github.com/euri10) was | ||||
|   quick to provide a fix: | ||||
|   [\#406](https://github.com/the-paperless-project/paperless/issues/406), | ||||
| @ -1669,13 +1876,13 @@ primarily. | ||||
| ### 2.4.0 | ||||
| 
 | ||||
| - A new set of actions are now available thanks to | ||||
|   [jonaswinkler](https://github.com/jonaswinkler)\'s very first pull | ||||
|   [jonaswinkler](https://github.com/jonaswinkler)'s very first pull | ||||
|   request! You can now do nifty things like tag documents in bulk, or | ||||
|   set correspondents in bulk. | ||||
|   [\#405](https://github.com/the-paperless-project/paperless/pull/405) | ||||
| - The import/export system is now a little smarter. By default, | ||||
|   documents are tagged as `unencrypted`, since exports are by their | ||||
|   nature unencrypted. It\'s now in the import step that we decide the | ||||
|   nature unencrypted. It's now in the import step that we decide the | ||||
|   storage type. This allows you to export from an encrypted system and | ||||
|   import into an unencrypted one, or vice-versa. | ||||
| - The migration history has been slightly modified to accommodate | ||||
| @ -1693,7 +1900,7 @@ primarily. | ||||
| 
 | ||||
| - Support for consuming plain text & markdown documents was added by | ||||
|   [Joshua Taillon](https://github.com/jat255)! This was a | ||||
|   long-requested feature, and it\'s addition is likely to be greatly | ||||
|   long-requested feature, and it's addition is likely to be greatly | ||||
|   appreciated by the community: | ||||
|   [\#395](https://github.com/the-paperless-project/paperless/pull/395) | ||||
|   Thanks also to [David Martin](https://github.com/ddddavidmartin) for | ||||
| @ -1734,7 +1941,7 @@ primarily. | ||||
|   lots of different tags: | ||||
|   [\#391](https://github.com/the-paperless-project/paperless/pull/391). | ||||
| - [Kilian Koeltzsch](https://github.com/kiliankoe) noticed a bug in | ||||
|   how we capture & automatically create tags, so that\'s fixed now | ||||
|   how we capture & automatically create tags, so that's fixed now | ||||
|   too: | ||||
|   [\#384](https://github.com/the-paperless-project/paperless/issues/384). | ||||
| - [erikarvstedt](https://github.com/erikarvstedt) tweaked the | ||||
| @ -1750,7 +1957,7 @@ primarily. | ||||
| - [Enno Lohmeier](https://github.com/elohmeier) added three simple | ||||
|   features that make Paperless a lot more user (and developer) | ||||
|   friendly: | ||||
|   1.  There\'s a new search box on the front page: | ||||
|   1.  There's a new search box on the front page: | ||||
|       [\#374](https://github.com/the-paperless-project/paperless/pull/374). | ||||
|   2.  The correspondents & tags pages now have a column showing the | ||||
|       number of relevant documents: | ||||
| @ -1760,18 +1967,18 @@ primarily. | ||||
|       environment: | ||||
|       [\#376](https://github.com/the-paperless-project/paperless/pull/376). | ||||
| - You now also have the ability to customise the interface to your | ||||
|   heart\'s content by creating a file called `overrides.css` and/or | ||||
|   heart's content by creating a file called `overrides.css` and/or | ||||
|   `overrides.js` in the root of your media directory. Thanks to [Mark | ||||
|   McFate](https://github.com/SummittDweller) for this idea: | ||||
|   [\#371](https://github.com/the-paperless-project/paperless/issues/371) | ||||
| 
 | ||||
| ### 2.0.0 | ||||
| 
 | ||||
| This is a big release as we\'ve changed a core-functionality of | ||||
| This is a big release as we've changed a core-functionality of | ||||
| Paperless: we no longer encrypt files with GPG by default. | ||||
| 
 | ||||
| The reasons for this are many, but it boils down to that the encryption | ||||
| wasn\'t really all that useful, as files on-disk were still accessible | ||||
| wasn't really all that useful, as files on-disk were still accessible | ||||
| so long as you had the key, and the key was most typically stored in the | ||||
| config file. In other words, your files are only as safe as the | ||||
| `paperless` user is. In addition to that, _the contents of the documents | ||||
| @ -1783,7 +1990,7 @@ explicitly set a passphrase in your config file. | ||||
| 
 | ||||
| ### Migrating from 1.x | ||||
| 
 | ||||
| Encryption isn\'t gone, it\'s just off for new users. So long as you | ||||
| Encryption isn't gone, it's just off for new users. So long as you | ||||
| have `PAPERLESS_PASSPHRASE` set in your config or your environment, | ||||
| Paperless should continue to operate as it always has. If however, you | ||||
| want to drop encryption too, you only need to do two things: | ||||
| @ -1813,7 +2020,7 @@ this big change. | ||||
|   for more information. | ||||
| - Refactor the use of travis/tox/pytest/coverage into two files: | ||||
|   `.travis.yml` and `setup.cfg`. | ||||
| - Start generating requirements.txt from a Pipfile. I\'ll probably | ||||
| - Start generating requirements.txt from a Pipfile. I'll probably | ||||
|   switch over to just using pipenv in the future. | ||||
| - All for a alternative FreeBSD-friendly location for | ||||
|   `paperless.conf`. Thanks to [Martin | ||||
| @ -1833,7 +2040,7 @@ this big change. | ||||
|   [\#253](https://github.com/the-paperless-project/paperless/issues/253) | ||||
|   and | ||||
|   [\#323](https://github.com/the-paperless-project/paperless/issues/323), | ||||
|   we\'ve removed a few of the hardcoded URL values to make it easier | ||||
|   we've removed a few of the hardcoded URL values to make it easier | ||||
|   for people to host Paperless on a subdirectory. Thanks to [Quentin | ||||
|   Dawans](https://github.com/ovv) and [Kyle | ||||
|   Lucy](https://github.com/kmlucy) for helping to work this out. | ||||
| @ -1846,7 +2053,7 @@ this big change. | ||||
|   very creating Bash skills: | ||||
|   [\#352](https://github.com/the-paperless-project/paperless/pull/352). | ||||
| - You can now use the search field to find documents by tag thanks to | ||||
|   [thinkjk](https://github.com/thinkjk)\'s _first ever issue_: | ||||
|   [thinkjk](https://github.com/thinkjk)'s _first ever issue_: | ||||
|   [\#354](https://github.com/the-paperless-project/paperless/issues/354). | ||||
| - Inotify is now being used to detect additions to the consume | ||||
|   directory thanks to some excellent work from | ||||
| @ -1855,7 +2062,7 @@ this big change. | ||||
| 
 | ||||
| ### 1.3.0 | ||||
| 
 | ||||
| - You can now run Paperless without a login, though you\'ll still have | ||||
| - You can now run Paperless without a login, though you'll still have | ||||
|   to create at least one user. This is thanks to a pull-request from | ||||
|   [matthewmoto](https://github.com/matthewmoto): | ||||
|   [\#295](https://github.com/the-paperless-project/paperless/pull/295). | ||||
| @ -1886,7 +2093,7 @@ this big change. | ||||
|   [\#312](https://github.com/the-paperless-project/paperless/pull/312) | ||||
|   to fix | ||||
|   [\#306](https://github.com/the-paperless-project/paperless/issues/306). | ||||
| - Patch the historical migrations to support MySQL\'s um, | ||||
| - Patch the historical migrations to support MySQL's um, | ||||
|   _interesting_ way of handing indexes | ||||
|   ([\#308](https://github.com/the-paperless-project/paperless/issues/308)). | ||||
|   Thanks to [Simon Taddiken](https://github.com/skuzzle) for reporting | ||||
| @ -1908,7 +2115,7 @@ this big change. | ||||
|   already contains text. This can be overridden by setting | ||||
|   `PAPERLESS_OCR_ALWAYS=YES` either in your `paperless.conf` or in the | ||||
|   environment. Note that this also means that Paperless now requires | ||||
|   `libpoppler-cpp-dev` to be installed. **Important**: You\'ll need to | ||||
|   `libpoppler-cpp-dev` to be installed. **Important**: You'll need to | ||||
|   run `pip install -r requirements.txt` after the usual `git pull` to | ||||
|   properly update. | ||||
| - [BastianPoe](https://github.com/BastianPoe) has also contributed a | ||||
| @ -1935,7 +2142,7 @@ this big change. | ||||
| 
 | ||||
| ### 1.0.0 | ||||
| 
 | ||||
| - Upgrade to Django 1.11. **You\'ll need to run \`\`pip install -r | ||||
| - Upgrade to Django 1.11. **You'll need to run \`\`pip install -r | ||||
|   requirements.txt\`\` after the usual \`\`git pull\`\` to properly | ||||
|   update**. | ||||
| - Replace the templatetag-based hack we had for document listing in | ||||
| @ -1956,14 +2163,14 @@ this big change. | ||||
|   [Pit](https://github.com/pitkley) on | ||||
|   [\#268](https://github.com/the-paperless-project/paperless/pull/268). | ||||
| - Date fields in the admin are now expressed as HTML5 date fields | ||||
|   thanks to [Lukas Winkler](https://github.com/Findus23)\'s issue | ||||
|   thanks to [Lukas Winkler](https://github.com/Findus23)'s issue | ||||
|   [\#278](https://github.com/the-paperless-project/paperless/issues/248) | ||||
| 
 | ||||
| ### 0.8.0 | ||||
| 
 | ||||
| - Paperless can now run in a subdirectory on a host (`/paperless`), | ||||
|   rather than always running in the root (`/`) thanks to | ||||
|   [maphy-psd](https://github.com/maphy-psd)\'s work on | ||||
|   [maphy-psd](https://github.com/maphy-psd)'s work on | ||||
|   [\#255](https://github.com/the-paperless-project/paperless/pull/255). | ||||
| 
 | ||||
| ### 0.7.0 | ||||
| @ -1972,14 +2179,14 @@ this big change. | ||||
|   [\#235](https://github.com/the-paperless-project/paperless/issues/235), | ||||
|   Paperless will no longer automatically delete documents attached to | ||||
|   correspondents when those correspondents are themselves deleted. | ||||
|   This was Django\'s default behaviour, but didn\'t make much sense in | ||||
|   Paperless\' case. Thanks to [Thomas | ||||
|   This was Django's default behaviour, but didn't make much sense in | ||||
|   Paperless' case. Thanks to [Thomas | ||||
|   Brueggemann](https://github.com/thomasbrueggemann) and [David | ||||
|   Martin](https://github.com/ddddavidmartin) for their input on this | ||||
|   one. | ||||
| - Fix for | ||||
|   [\#232](https://github.com/the-paperless-project/paperless/issues/232) | ||||
|   wherein Paperless wasn\'t recognising `.tif` files properly. Thanks | ||||
|   wherein Paperless wasn't recognising `.tif` files properly. Thanks | ||||
|   to [ayounggun](https://github.com/ayounggun) for reporting this one | ||||
|   and to [Kusti Skytén](https://github.com/kskyten) for posting the | ||||
|   correct solution in the Github issue. | ||||
| @ -1990,12 +2197,12 @@ this big change. | ||||
|   favour of BasicAuth or Django session. | ||||
| - Fix the POST API so it actually works. | ||||
|   [\#236](https://github.com/the-paperless-project/paperless/issues/236) | ||||
| - **Breaking change**: We\'ve dropped the use of | ||||
| - **Breaking change**: We've dropped the use of | ||||
|   `PAPERLESS_SHARED_SECRET` as it was being used both for the API (now | ||||
|   replaced with a normal auth) and form email polling. Now that we\'re | ||||
|   replaced with a normal auth) and form email polling. Now that we're | ||||
|   only using it for email, this variable has been renamed to | ||||
|   `PAPERLESS_EMAIL_SECRET`. The old value will still work for a while, | ||||
|   but you should change your config if you\'ve been using the email | ||||
|   but you should change your config if you've been using the email | ||||
|   polling feature. Thanks to [Joshua | ||||
|   Gilman](https://github.com/jmgilman) for all the help with this | ||||
|   feature. | ||||
| @ -2003,7 +2210,7 @@ this big change. | ||||
| ### 0.5.0 | ||||
| 
 | ||||
| - Support for fuzzy matching in the auto-tagger & auto-correspondent | ||||
|   systems thanks to [Jake Gysland](https://github.com/jgysland)\'s | ||||
|   systems thanks to [Jake Gysland](https://github.com/jgysland)'s | ||||
|   patch | ||||
|   [\#220](https://github.com/the-paperless-project/paperless/pull/220). | ||||
| - Modified the Dockerfile to prepare an export directory | ||||
| @ -2032,7 +2239,7 @@ this big change. | ||||
| 
 | ||||
| - Fix for | ||||
|   [\#206](https://github.com/the-paperless-project/paperless/issues/206) | ||||
|   wherein the pluggable parser didn\'t recognise files with all-caps | ||||
|   wherein the pluggable parser didn't recognise files with all-caps | ||||
|   suffixes like `.PDF` | ||||
| 
 | ||||
| ### 0.4.0 | ||||
| @ -2042,7 +2249,7 @@ this big change. | ||||
|   for more information, but the short explanation is that you can now | ||||
|   attach simple notes & times to documents which are made available | ||||
|   via the API. Currently, the default API (basically just the Django | ||||
|   admin) doesn\'t really make use of this, but [Thomas | ||||
|   admin) doesn't really make use of this, but [Thomas | ||||
|   Brueggemann](https://github.com/thomasbrueggemann) over at | ||||
|   [Paperless | ||||
|   Desktop](https://github.com/thomasbrueggemann/paperless-desktop) has | ||||
| @ -2052,16 +2259,16 @@ this big change. | ||||
| 
 | ||||
| - Fix for | ||||
|   [\#200](https://github.com/the-paperless-project/paperless/issues/200) | ||||
|   (!!) where the API wasn\'t configured to allow updating the | ||||
|   (!!) where the API wasn't configured to allow updating the | ||||
|   correspondent or the tags for a document. | ||||
| - The `content` field is now optional, to allow for the edge case of a | ||||
|   purely graphical document. | ||||
| - You can no longer add documents via the admin. This never worked in | ||||
|   the first place, so all I\'ve done here is remove the link to the | ||||
|   the first place, so all I've done here is remove the link to the | ||||
|   broken form. | ||||
| - The consumer code has been heavily refactored to support a pluggable | ||||
|   interface. Install a paperless consumer via pip and tell paperless | ||||
|   about it with an environment variable, and you\'re good to go. | ||||
|   about it with an environment variable, and you're good to go. | ||||
|   Proper documentation is on its way. | ||||
| 
 | ||||
| ### 0.3.5 | ||||
| @ -2082,10 +2289,10 @@ this big change. | ||||
| - Removal of django-suit due to a licensing conflict I bumped into in | ||||
|   0.3.3. Note that you _can_ use Django Suit with Paperless, but only | ||||
|   in a non-profit situation as their free license prohibits for-profit | ||||
|   use. As a result, I can\'t bundle Suit with Paperless without | ||||
|   use. As a result, I can't bundle Suit with Paperless without | ||||
|   conflicting with the GPL. Further development will be done against | ||||
|   the stock Django admin. | ||||
| - I shrunk the thumbnails a little \'cause they were too big for me, | ||||
| - I shrunk the thumbnails a little 'cause they were too big for me, | ||||
|   even on my high-DPI monitor. | ||||
| - BasicAuth support for document and thumbnail downloads, as well as | ||||
|   the Push API thanks to \@thomasbrueggemann. See | ||||
| @ -2112,14 +2319,14 @@ this big change. | ||||
| ### 0.3.0 | ||||
| 
 | ||||
| - Updated to using django-filter 1.x | ||||
| - Added some system checks so new users aren\'t confused by | ||||
| - Added some system checks so new users aren't confused by | ||||
|   misconfigurations. | ||||
| - Consumer loop time is now configurable for systems with slow writes. | ||||
|   Just set `PAPERLESS_CONSUMER_LOOP_TIME` to a number of seconds. The | ||||
|   default is 10. | ||||
| - As per | ||||
|   [\#44](https://github.com/the-paperless-project/paperless/issues/44), | ||||
|   we\'ve removed support for `PAPERLESS_CONVERT`, `PAPERLESS_CONSUME`, | ||||
|   we've removed support for `PAPERLESS_CONVERT`, `PAPERLESS_CONSUME`, | ||||
|   and `PAPERLESS_SECRET`. Please use `PAPERLESS_CONVERT_BINARY`, | ||||
|   `PAPERLESS_CONSUMPTION_DIR`, and `PAPERLESS_SHARED_SECRET` | ||||
|   respectively instead. | ||||
| @ -2134,17 +2341,17 @@ this big change. | ||||
| - [\#146](https://github.com/the-paperless-project/paperless/issues/146): | ||||
|   Fixed a bug that allowed unauthorised access to the `/fetch` URL. | ||||
| - [\#131](https://github.com/the-paperless-project/paperless/issues/131): | ||||
|   Document files are now automatically removed from disk when they\'re | ||||
|   Document files are now automatically removed from disk when they're | ||||
|   deleted in Paperless. | ||||
| - [\#121](https://github.com/the-paperless-project/paperless/issues/121): | ||||
|   Fixed a bug where Paperless wasn\'t setting document creation time | ||||
|   Fixed a bug where Paperless wasn't setting document creation time | ||||
|   based on the file naming scheme. | ||||
| - [\#81](https://github.com/the-paperless-project/paperless/issues/81): | ||||
|   Added a hook to run an arbitrary script after every document is | ||||
|   consumed. | ||||
| - [\#98](https://github.com/the-paperless-project/paperless/issues/98): | ||||
|   Added optional environment variables for ImageMagick so that it | ||||
|   doesn\'t explode when handling Very Large Documents or when it\'s | ||||
|   doesn't explode when handling Very Large Documents or when it's | ||||
|   just running on a low-memory system. Thanks to [Florian | ||||
|   Harr](https://github.com/evils) for his help on this one. | ||||
| - [\#89](https://github.com/the-paperless-project/paperless/issues/89) | ||||
| @ -2163,8 +2370,8 @@ this big change. | ||||
| 
 | ||||
| ### 0.1.1 | ||||
| 
 | ||||
| - Potentially **Breaking Change**: All references to \"sender\" in the | ||||
|   code have been renamed to \"correspondent\" to better reflect the | ||||
| - Potentially **Breaking Change**: All references to "sender" in the | ||||
|   code have been renamed to "correspondent" to better reflect the | ||||
|   nature of the property (one could quite reasonably scan a document | ||||
|   before sending it to someone.) | ||||
| - [\#67](https://github.com/the-paperless-project/paperless/issues/67): | ||||
| @ -2178,7 +2385,7 @@ this big change. | ||||
|   contributing conversation that lead to this change. | ||||
| - [\#20](https://github.com/the-paperless-project/paperless/issues/20): | ||||
|   Added _unpaper_ support to help in cleaning up the scanned image | ||||
|   before it\'s OCR\'d. Thanks to [Pit](https://github.com/pitkley) for | ||||
|   before it's OCR'd. Thanks to [Pit](https://github.com/pitkley) for | ||||
|   this one. | ||||
| - [\#71](https://github.com/the-paperless-project/paperless/issues/71) | ||||
|   Added (encrypted) thumbnails in anticipation of a proper UI. | ||||
|  | ||||
							
								
								
									
										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 "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 "Example: https://paperless.example.com" | ||||
| echo "" | ||||
| 
 | ||||
| ask "URL" "" | ||||
| @ -112,6 +113,8 @@ echo "" | ||||
| 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 "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 "" | ||||
| 
 | ||||
| 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. | ||||
| # https://paperless-ngx.readthedocs.io/en/latest/configuration.html | ||||
| # https://docs.paperless-ngx.com/configuration/ | ||||
| 
 | ||||
| # 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 -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 | ||||
|  | ||||
| @ -35,6 +35,16 @@ describe('settings', () => { | ||||
|             req.reply(response) | ||||
|           } | ||||
|         ).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) => { | ||||
| @ -48,7 +58,6 @@ describe('settings', () => { | ||||
| 
 | ||||
|     cy.viewport(1024, 1600) | ||||
|     cy.visit('/settings') | ||||
|     cy.wait('@savedViews') | ||||
|   }) | ||||
| 
 | ||||
|   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', () => { | ||||
|     cy.contains('a', 'Saved views').click() | ||||
|     cy.contains('a', 'Saved views').click().wait(2000) | ||||
|     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') | ||||
|   }) | ||||
| 
 | ||||
|   it('should remove saved view from dashboard when unset', () => { | ||||
|     cy.contains('a', 'Saved views').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.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', () => { | ||||
|     cy.get('thead').find('input[type="checkbox"]').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", | ||||
|     "@ng-bootstrap/ng-bootstrap": "^13.0.0", | ||||
|     "@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", | ||||
|     "bootstrap": "^5.2.1", | ||||
|     "file-saver": "^2.0.5", | ||||
|     "ng2-pdf-viewer": "^9.1.2", | ||||
|     "ngx-color": "^8.0.3", | ||||
|     "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", | ||||
|     "rxjs": "~7.5.7", | ||||
|     "tslib": "^2.3.1", | ||||
|     "tslib": "^2.4.1", | ||||
|     "uuid": "^9.0.0", | ||||
|     "zone.js": "~0.11.8" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "@angular-builders/jest": "14.0.1", | ||||
|     "@angular-builders/jest": "14.1.0", | ||||
|     "@angular-devkit/build-angular": "~14.2.7", | ||||
|     "@angular/cli": "~14.2.7", | ||||
|     "@angular/compiler-cli": "~14.2.8", | ||||
| @ -48,7 +48,7 @@ | ||||
|     "concurrently": "7.4.0", | ||||
|     "jest": "28.1.3", | ||||
|     "jest-environment-jsdom": "^29.2.2", | ||||
|     "jest-preset-angular": "^12.2.2", | ||||
|     "jest-preset-angular": "^12.2.3", | ||||
|     "ts-node": "~10.9.1", | ||||
|     "tslint": "~6.1.3", | ||||
|     "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([ | ||||
|       { | ||||
|         anchorId: 'tour.dashboard', | ||||
| @ -142,12 +146,18 @@ export class AppComponent implements OnInit, OnDestroy { | ||||
|         route: '/dashboard', | ||||
|         enableBackdrop: true, | ||||
|         delayAfterNavigation: 500, | ||||
|         prevBtnTitle, | ||||
|         nextBtnTitle, | ||||
|         endBtnTitle, | ||||
|       }, | ||||
|       { | ||||
|         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.`, | ||||
|         route: '/dashboard', | ||||
|         enableBackdrop: true, | ||||
|         prevBtnTitle, | ||||
|         nextBtnTitle, | ||||
|         endBtnTitle, | ||||
|       }, | ||||
|       { | ||||
|         anchorId: 'tour.documents', | ||||
| @ -157,6 +167,9 @@ export class AppComponent implements OnInit, OnDestroy { | ||||
|         placement: 'bottom', | ||||
|         enableBackdrop: true, | ||||
|         disableScrollToAnchor: true, | ||||
|         prevBtnTitle, | ||||
|         nextBtnTitle, | ||||
|         endBtnTitle, | ||||
|       }, | ||||
|       { | ||||
|         anchorId: 'tour.documents-filter-editor', | ||||
| @ -164,35 +177,45 @@ export class AppComponent implements OnInit, OnDestroy { | ||||
|         route: '/documents?sort=created&reverse=1&page=1', | ||||
|         placement: 'bottom', | ||||
|         enableBackdrop: true, | ||||
|         prevBtnTitle, | ||||
|         nextBtnTitle, | ||||
|         endBtnTitle, | ||||
|       }, | ||||
|       { | ||||
|         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.`, | ||||
|         route: '/documents?sort=created&reverse=1&page=1', | ||||
|         enableBackdrop: true, | ||||
|         prevBtnTitle, | ||||
|         nextBtnTitle, | ||||
|         endBtnTitle, | ||||
|       }, | ||||
|       { | ||||
|         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.`, | ||||
|         route: '/tags', | ||||
|         enableBackdrop: true, | ||||
|         prevBtnTitle, | ||||
|         nextBtnTitle, | ||||
|         endBtnTitle, | ||||
|       }, | ||||
|       { | ||||
|         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.`, | ||||
|         route: '/tasks', | ||||
|         enableBackdrop: true, | ||||
|         prevBtnTitle, | ||||
|         nextBtnTitle, | ||||
|         endBtnTitle, | ||||
|       }, | ||||
|       { | ||||
|         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', | ||||
|         enableBackdrop: true, | ||||
|       }, | ||||
|       { | ||||
|         anchorId: 'tour.admin', | ||||
|         content: $localize`The Admin area contains more advanced controls as well as the settings for automatic e-mail fetching.`, | ||||
|         enableBackdrop: true, | ||||
|         prevBtnTitle, | ||||
|         nextBtnTitle, | ||||
|         endBtnTitle, | ||||
|       }, | ||||
|       { | ||||
|         anchorId: 'tour.outro', | ||||
| @ -202,6 +225,9 @@ export class AppComponent implements OnInit, OnDestroy { | ||||
|           '<br/><br/>' + | ||||
|           $localize`Lastly, on behalf of every contributor to this community-supported project, thank you for using Paperless-ngx!`, | ||||
|         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 { SelectComponent } from './components/common/input/select/select.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 { TagsComponent } from './components/common/input/tags/tags.component' | ||||
| 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 { GroupEditDialogComponent } from './components/common/edit-dialog/group-edit-dialog/group-edit-dialog.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 localeCs from '@angular/common/locales/cs' | ||||
| @ -162,6 +165,7 @@ function initializeApp(settings: SettingsService) { | ||||
|     TextComponent, | ||||
|     SelectComponent, | ||||
|     CheckComponent, | ||||
|     PasswordComponent, | ||||
|     SaveViewConfigDialogComponent, | ||||
|     TagsComponent, | ||||
|     IfPermissionsDirective, | ||||
| @ -189,6 +193,8 @@ function initializeApp(settings: SettingsService) { | ||||
|     UserEditDialogComponent, | ||||
|     GroupEditDialogComponent, | ||||
|     PermissionsSelectComponent, | ||||
|     MailAccountEditDialogComponent, | ||||
|     MailRuleEditDialogComponent, | ||||
|   ], | ||||
|   imports: [ | ||||
|     BrowserModule, | ||||
|  | ||||
| @ -17,7 +17,7 @@ | ||||
|       </svg> | ||||
|       <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> | ||||
|       <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"> | ||||
|           <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> | ||||
| @ -177,13 +177,6 @@ | ||||
|               </svg><span> <ng-container i18n>Settings</ng-container></span> | ||||
|             </a> | ||||
|           </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> | ||||
| 
 | ||||
|         <h6 class="sidebar-heading px-3 mt-auto pt-4 mb-1 text-muted"> | ||||
| @ -191,7 +184,7 @@ | ||||
|         </h6> | ||||
|         <ul class="nav flex-column mb-2"> | ||||
|           <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"> | ||||
|                 <use xlink:href="assets/bootstrap-icons.svg#question-circle"/> | ||||
|               </svg><span> <ng-container i18n>Documentation</ng-container></span> | ||||
|  | ||||
| @ -97,6 +97,15 @@ export class AppFrameComponent | ||||
|     this.isMenuCollapsed = true | ||||
|   } | ||||
| 
 | ||||
|   get openDocuments(): PaperlessDocument[] { | ||||
|     return this.openDocumentsService.getOpenDocuments() | ||||
|   } | ||||
| 
 | ||||
|   @HostListener('window:beforeunload') | ||||
|   canDeactivate(): Observable<boolean> | boolean { | ||||
|     return !this.openDocumentsService.hasDirty() | ||||
|   } | ||||
| 
 | ||||
|   searchField = new FormControl('') | ||||
| 
 | ||||
|   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>) => | ||||
|     text$.pipe( | ||||
|       debounceTime(200), | ||||
|  | ||||