Compare commits
1737 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
8da85d3609 | ||
![]() |
127d30918d | ||
![]() |
3b553f6455 | ||
![]() |
6d934da5dd | ||
![]() |
aa3d91a338 | ||
![]() |
d64818b46c | ||
![]() |
99a18516b2 | ||
![]() |
30b0a30146 | ||
![]() |
cb10617979 | ||
![]() |
265432f2a5 | ||
![]() |
a13e9f23b1 | ||
![]() |
65b37f61ca | ||
![]() |
7751755399 | ||
![]() |
14e2ad7bc4 | ||
![]() |
dfc23a2b38 | ||
![]() |
d2fc840293 | ||
![]() |
37fe6fb9c3 | ||
![]() |
a21ec76997 | ||
![]() |
501d8d9683 | ||
![]() |
8562ca9a77 | ||
![]() |
29641e5d66 | ||
![]() |
ee7308be2d | ||
![]() |
ef4009e94f | ||
![]() |
27d2ae6976 | ||
![]() |
0f9675f9d6 | ||
![]() |
bac4a63cc8 | ||
![]() |
0453787d38 | ||
![]() |
afc3e41f13 | ||
![]() |
86d6316cc9 | ||
![]() |
7b2c1f82f5 | ||
![]() |
e2a932d744 | ||
![]() |
b978994525 | ||
![]() |
6da237dd9e | ||
![]() |
50c1978d36 | ||
![]() |
fdb310c497 | ||
![]() |
ce121a261d | ||
![]() |
ebdfd4241a | ||
![]() |
9cbb1c5726 | ||
![]() |
85dabccbe7 | ||
![]() |
a9a8189d4b | ||
![]() |
30579112d2 | ||
![]() |
ccfd009c1a | ||
![]() |
044a939623 | ||
![]() |
203bc162cd | ||
![]() |
31f03ef1d3 | ||
![]() |
4d3552dc64 | ||
![]() |
ea8a52404f | ||
![]() |
0ae9aecdef | ||
![]() |
4de4789605 | ||
![]() |
950bb46827 | ||
![]() |
44936dc5f0 | ||
![]() |
1140a878b4 | ||
![]() |
efb49af7ac | ||
![]() |
b5a8106a6a | ||
![]() |
0f80eee54e | ||
![]() |
0e237fa459 | ||
![]() |
702b985ceb | ||
![]() |
7d87bcbb98 | ||
![]() |
340521aa0d | ||
![]() |
7bc557a999 | ||
![]() |
dfa7cdf47e | ||
![]() |
0d78e58d77 | ||
![]() |
58df3d5767 | ||
![]() |
4e4d6e806c | ||
![]() |
6ff99945f3 | ||
![]() |
b7f1b9f8ad | ||
![]() |
08a44cf468 | ||
![]() |
a1162d6d5a | ||
![]() |
1c81d88013 | ||
![]() |
1e4ec7e29e | ||
![]() |
2c4e34dd0c | ||
![]() |
cb308fae7b | ||
![]() |
3f03d51b24 | ||
![]() |
831db6ab87 | ||
![]() |
43fdf634f2 | ||
![]() |
f07a6b4586 | ||
![]() |
2fcf484229 | ||
![]() |
8bf4241b16 | ||
![]() |
56bd966c02 | ||
![]() |
416101d557 | ||
![]() |
c330cca2c9 | ||
![]() |
7e88085377 | ||
![]() |
5e669534f2 | ||
![]() |
98b147b622 | ||
![]() |
df6c59bc4f | ||
![]() |
6e48da41e5 | ||
![]() |
5c8a01a6e8 | ||
![]() |
3d0a52c25f | ||
![]() |
43c729568b | ||
![]() |
62caeed283 | ||
![]() |
12836d4c68 | ||
![]() |
b48e67d714 | ||
![]() |
f91f4d71bb | ||
![]() |
0a1f264c71 | ||
![]() |
64d61ae2fa | ||
![]() |
5f0e800f6e | ||
![]() |
8b2965d55b | ||
![]() |
ed478a1d73 | ||
![]() |
13e91d8c95 | ||
![]() |
6ac90181cb | ||
![]() |
d6c3471909 | ||
![]() |
5b56fad9c7 | ||
![]() |
ed0b1fe115 | ||
![]() |
4211153527 | ||
![]() |
2f85461109 | ||
![]() |
3fa7dcb0cb | ||
![]() |
857fe3a55c | ||
![]() |
dd19ea46fe | ||
![]() |
21740a9d87 | ||
![]() |
658fb2f208 | ||
![]() |
252d4cb513 | ||
![]() |
5aed41223b | ||
![]() |
45dfbf3747 | ||
![]() |
e4fe5bebab | ||
![]() |
04519ee623 | ||
![]() |
6c8f010f7a | ||
![]() |
ed84cf26e7 | ||
![]() |
1bc961f0c0 | ||
![]() |
77d745381f | ||
![]() |
7082cb9c36 | ||
![]() |
34e84cc757 | ||
![]() |
9246411610 | ||
![]() |
8330b3598c | ||
![]() |
1d002149dc | ||
![]() |
8d6071e977 | ||
![]() |
7d67766508 | ||
![]() |
887dd122fe | ||
![]() |
a1293c77b9 | ||
![]() |
ee9a73aa95 | ||
![]() |
9df332b614 | ||
![]() |
d13e86a892 | ||
![]() |
69d7f8c180 | ||
![]() |
1ba89ddd09 | ||
![]() |
0c40a28ad3 | ||
![]() |
2b7424c42a | ||
![]() |
a9f1766d1c | ||
![]() |
fca8576d80 | ||
![]() |
05f59e7d5e | ||
![]() |
c9511680b3 | ||
![]() |
0ed001c56e | ||
![]() |
1e5a418191 | ||
![]() |
e05735bc0f | ||
![]() |
7621e10840 | ||
![]() |
d90080f325 | ||
![]() |
0c676b90f2 | ||
![]() |
c2d8bda83c | ||
![]() |
302ebf737e | ||
![]() |
816c95a4ae | ||
![]() |
40106f6fcc | ||
![]() |
61143b3ad1 | ||
![]() |
9b64eebd10 | ||
![]() |
731418349f | ||
![]() |
7728920670 | ||
![]() |
f555bb95ae | ||
![]() |
bcee17c3ac | ||
![]() |
7bc16edfe2 | ||
![]() |
40f3e8e45a | ||
![]() |
656b4708ac | ||
![]() |
7702f5012b | ||
![]() |
ffe96c8fff | ||
![]() |
0024c2aae4 | ||
![]() |
ed39e9e15f | ||
![]() |
fd8c40fee7 | ||
![]() |
0e76441684 | ||
![]() |
d2c34fb9c7 | ||
![]() |
d09ea8408c | ||
![]() |
e8a1fde1c7 | ||
![]() |
5ef6f2697e | ||
![]() |
80b3fa75a5 | ||
![]() |
9993381cda | ||
![]() |
9fa3f91e8a | ||
![]() |
fe435f6653 | ||
![]() |
5696c02ac3 | ||
![]() |
019dfeb3ee | ||
![]() |
e35723e7af | ||
![]() |
1d50d017ac | ||
![]() |
9e5d1ad952 | ||
![]() |
9faaf4b1e4 | ||
![]() |
ac229ce004 | ||
![]() |
968614a289 | ||
![]() |
2f68f236bb | ||
![]() |
00903bd90c | ||
![]() |
96d7114fa7 | ||
![]() |
431d4fd8e4 | ||
![]() |
0d3ab3aaf7 | ||
![]() |
138f38d1f3 | ||
![]() |
222fb48378 | ||
![]() |
5718f50c4f | ||
![]() |
d8e0ef257e | ||
![]() |
866c8fc848 | ||
![]() |
758631c53f | ||
![]() |
8711a206a0 | ||
![]() |
44ec3a3d9c | ||
![]() |
883a6b26a4 | ||
![]() |
b9e1ed7d7e | ||
![]() |
c51fa60172 | ||
![]() |
e300ee0c92 | ||
![]() |
ba3c8308b3 | ||
![]() |
63b11514c9 | ||
![]() |
49d2084d8a | ||
![]() |
c36fe577de | ||
![]() |
28c79f1abb | ||
![]() |
a1f07417da | ||
![]() |
611b4fe31b | ||
![]() |
697670ef97 | ||
![]() |
ee487529fe | ||
![]() |
2129cda38d | ||
![]() |
afb63f763a | ||
![]() |
a186d6fae2 | ||
![]() |
d17de45791 | ||
![]() |
18980bbbe3 | ||
![]() |
32c9369ba1 | ||
![]() |
bdc247ce49 | ||
![]() |
85f46424a8 | ||
![]() |
d198a89f22 | ||
![]() |
82730ab491 | ||
![]() |
c78d54e71e | ||
![]() |
08d96a1b76 | ||
![]() |
b2a744e880 | ||
![]() |
3f421a4f64 | ||
![]() |
2624aec758 | ||
![]() |
f3a18c26f4 | ||
![]() |
47ea60372f | ||
![]() |
8efba4c57f | ||
![]() |
060dcd71cd | ||
![]() |
fd6e727299 | ||
![]() |
c4adb20eff | ||
![]() |
e70af00321 | ||
![]() |
9ebe16d823 | ||
![]() |
fd05da96d5 | ||
![]() |
5f44ab5abc | ||
![]() |
ffc82c17ba | ||
![]() |
b33e25b1f7 | ||
![]() |
55c50e3ac2 | ||
![]() |
211a88129e | ||
![]() |
2a629b81ce | ||
![]() |
2efb99192a | ||
![]() |
0a28ccf62f | ||
![]() |
48b042bfb0 | ||
![]() |
da08eec91f | ||
![]() |
684f91b2e3 | ||
![]() |
689579c7f2 | ||
![]() |
4a549ccd33 | ||
![]() |
32f0a2fdbc | ||
![]() |
abee54ebe3 | ||
![]() |
58ae14c364 | ||
![]() |
34104f0d42 | ||
![]() |
dabcdbad00 | ||
![]() |
4c314130f7 | ||
![]() |
53a71384b0 | ||
![]() |
294a5ebec6 | ||
![]() |
6a4b31b354 | ||
![]() |
76c9715748 | ||
![]() |
e657ca7496 | ||
![]() |
ddf01eef14 | ||
![]() |
3d093f2c08 | ||
![]() |
004e3134fc | ||
![]() |
85ee74f2d8 | ||
![]() |
406ec17050 | ||
![]() |
7f85180264 | ||
![]() |
ad29fc23a6 | ||
![]() |
b9690de9ab | ||
![]() |
d4deefc81c | ||
![]() |
32780472db | ||
![]() |
b1f906461e | ||
![]() |
7e449d661b | ||
![]() |
24b3a03000 | ||
![]() |
cd28fbf563 | ||
![]() |
d7b2906977 | ||
![]() |
3180b38797 | ||
![]() |
fd59def1bd | ||
![]() |
8cd1dd71e8 | ||
![]() |
48cfb64416 | ||
![]() |
adb76eafaf | ||
![]() |
4e2efebaa7 | ||
![]() |
eb6153c5aa | ||
![]() |
9c3b16c879 | ||
![]() |
ba637c8582 | ||
![]() |
46ea86a6d2 | ||
![]() |
9d148c08ce | ||
![]() |
ac459f7b05 | ||
![]() |
35a4779cc0 | ||
![]() |
ffa44f51cd | ||
![]() |
682a9d2a09 | ||
![]() |
4c6a02aee7 | ||
![]() |
87a18eae2d | ||
![]() |
269673ce05 | ||
![]() |
d9e06958dc | ||
![]() |
063bfc245c | ||
![]() |
21c501de28 | ||
![]() |
d50d1bd2ea | ||
![]() |
e4aa31a62d | ||
![]() |
fdf58bed6a | ||
![]() |
a54784da11 | ||
![]() |
a40e4fe3bc | ||
![]() |
ea30fbf14f | ||
![]() |
d22d9a023c | ||
![]() |
ddcc0883eb | ||
![]() |
047a21eb48 | ||
![]() |
439f06ccda | ||
![]() |
05866da04b | ||
![]() |
dcd350a30c | ||
![]() |
107cc2ca20 | ||
![]() |
f872221c49 | ||
![]() |
2faa425caf | ||
![]() |
94be8781e9 | ||
![]() |
47189342e4 | ||
![]() |
fafe259e53 | ||
![]() |
41fe607157 | ||
![]() |
062008269b | ||
![]() |
29e1b51164 | ||
![]() |
d2a8bc5c4c | ||
![]() |
7414b3d23a | ||
![]() |
a0a781a3d5 | ||
![]() |
d9e6f6e07c | ||
![]() |
9167357908 | ||
![]() |
3b541b22e8 | ||
![]() |
71d5af233d | ||
![]() |
b0ed06003b | ||
![]() |
91f7c4e685 | ||
![]() |
5a4cb5fe4a | ||
![]() |
cc74be9ccc | ||
![]() |
68a9dd7e05 | ||
![]() |
682cf33c78 | ||
![]() |
763b780aa4 | ||
![]() |
24313fe001 | ||
![]() |
51dc40ae73 | ||
![]() |
ab04817bea | ||
![]() |
8dde7fa043 | ||
![]() |
edfebe18a2 | ||
![]() |
0b07c3bd8f | ||
![]() |
1483f450ad | ||
![]() |
600c13204e | ||
![]() |
2073279473 | ||
![]() |
d126ecfa4d | ||
![]() |
944aaf5438 | ||
![]() |
52f17a9ba6 | ||
![]() |
44600961d8 | ||
![]() |
d60b532b8f | ||
![]() |
55584a6a87 | ||
![]() |
7c02a8b414 | ||
![]() |
18d105b4f8 | ||
![]() |
f0d49a1382 | ||
![]() |
277bf0eb83 | ||
![]() |
3b5d55c428 | ||
![]() |
313f2886d7 | ||
![]() |
868fd4155a | ||
![]() |
4eeb5642f5 | ||
![]() |
532a3d955c | ||
![]() |
53309f017f | ||
![]() |
5651a03b14 | ||
![]() |
7dedb99dae | ||
![]() |
b581e42216 | ||
![]() |
ede3bd1391 | ||
![]() |
339e96b63c | ||
![]() |
f31073a341 | ||
![]() |
2fa78f7820 | ||
![]() |
77b85b9e93 | ||
![]() |
29ce2515ee | ||
![]() |
d57c237980 | ||
![]() |
37ade0c6b2 | ||
![]() |
28a2479f24 | ||
![]() |
be2013975c | ||
![]() |
6e688a5b82 | ||
![]() |
bfbdfe857f | ||
![]() |
0d19957d4b | ||
![]() |
05d69c0882 | ||
![]() |
2104e65462 | ||
![]() |
c0882e74e2 | ||
![]() |
ced6a61869 | ||
![]() |
6c3b1db4dd | ||
![]() |
25a0845efd | ||
![]() |
8d62493774 | ||
![]() |
eca1289ce2 | ||
![]() |
f95fd4ced2 | ||
![]() |
227f7b6946 | ||
![]() |
1a0b954397 | ||
![]() |
87ad2ce1d6 | ||
![]() |
63cd16e29e | ||
![]() |
66fc9e9111 | ||
![]() |
43bee38b3c | ||
![]() |
18ebb58dc9 | ||
![]() |
099b84a66d | ||
![]() |
3b22d7131d | ||
![]() |
11f9616411 | ||
![]() |
10b53bdfd0 | ||
![]() |
aeb10d3407 | ||
![]() |
ddf386c4d4 | ||
![]() |
9575b0fe32 | ||
![]() |
6c7290bd34 | ||
![]() |
19032fe433 | ||
![]() |
8fce8d4677 | ||
![]() |
2333ea9dc7 | ||
![]() |
937cdaccad | ||
![]() |
54916fec2e | ||
![]() |
03e159f67c | ||
![]() |
482ef6313d | ||
![]() |
43685baff3 | ||
![]() |
f6a2cc74e8 | ||
![]() |
9f1436a865 | ||
![]() |
020df6c8ea | ||
![]() |
08046cb83f | ||
![]() |
f06edebbd8 | ||
![]() |
c808011b75 | ||
![]() |
da60fc8150 | ||
![]() |
04a0d01b21 | ||
![]() |
02a066f8f3 | ||
![]() |
7834d369c6 | ||
![]() |
5e841531be | ||
![]() |
5355f2b027 | ||
![]() |
e1533202fc | ||
![]() |
0b949a14c0 | ||
![]() |
5175206179 | ||
![]() |
0af0dffeda | ||
![]() |
74a1b36005 | ||
![]() |
8884a4dfdf | ||
![]() |
19f73f5782 | ||
![]() |
8e95310602 | ||
![]() |
fe31b8d160 | ||
![]() |
6515d1ae85 | ||
![]() |
a8ec9f29cd | ||
![]() |
bab53838ec | ||
![]() |
bf2e98527c | ||
![]() |
e1e11de2b5 | ||
![]() |
4fda8f3348 | ||
![]() |
8427d58337 | ||
![]() |
385076cf28 | ||
![]() |
b9725437d9 | ||
![]() |
72616def4f | ||
![]() |
6c972bd08a | ||
![]() |
a71a991084 | ||
![]() |
0927f9d477 | ||
![]() |
a68b858733 | ||
![]() |
08199f09b6 | ||
![]() |
5f8151282b | ||
![]() |
efde4828d6 | ||
![]() |
016c168404 | ||
![]() |
741ccfa280 | ||
![]() |
31b74515b6 | ||
![]() |
b9a2f82ce0 | ||
![]() |
3c59d9b787 | ||
![]() |
f919ec0d57 | ||
![]() |
9c380f5aac | ||
![]() |
fc5def157d | ||
![]() |
d5eff386db | ||
![]() |
864e421cd3 | ||
![]() |
2c9825193b | ||
![]() |
98f3e99e2e | ||
![]() |
961354aa8a | ||
![]() |
fa27c895ed | ||
![]() |
c31b6e63f5 | ||
![]() |
ef924e896b | ||
![]() |
5b1619cba3 | ||
![]() |
a3a9949ebc | ||
![]() |
ada8493838 | ||
![]() |
cc06d528cb | ||
![]() |
0926266663 | ||
![]() |
59008ea765 | ||
![]() |
01cd4c7546 | ||
![]() |
8d606b9f34 | ||
![]() |
86376c8c5f | ||
![]() |
48220ceeb8 | ||
![]() |
f94da1cf27 | ||
![]() |
6d786f8987 | ||
![]() |
8d433ac0de | ||
![]() |
4b42c97d0a | ||
![]() |
d8637ff4b1 | ||
![]() |
342e9c9734 | ||
![]() |
af1d084391 | ||
![]() |
e6961d5287 | ||
![]() |
7562bdb218 | ||
![]() |
cb94e15ba7 | ||
![]() |
c8b0674b93 | ||
![]() |
4fa1779ef3 | ||
![]() |
db23a5cf37 | ||
![]() |
7cc3c73994 | ||
![]() |
014859185c | ||
![]() |
6dae900d74 | ||
![]() |
a4187b2b70 | ||
![]() |
556e4f7430 | ||
![]() |
02c2d388ed | ||
![]() |
c0692f03a3 | ||
![]() |
a2342d98d3 | ||
![]() |
24c20e38ff | ||
![]() |
cd12c1b300 | ||
![]() |
a008dff368 | ||
![]() |
769356733a | ||
![]() |
f5be2ac4bb | ||
![]() |
2824fcb497 | ||
![]() |
2f42eab217 | ||
![]() |
338324d5b6 | ||
![]() |
0628d10076 | ||
![]() |
bc4017d54a | ||
![]() |
96dc7583bf | ||
![]() |
deb9698ff6 | ||
![]() |
654c7fd2ac | ||
![]() |
24e34e95cd | ||
![]() |
d093c004fb | ||
![]() |
ceb9426fd4 | ||
![]() |
e4f2016678 | ||
![]() |
40842689fd | ||
![]() |
59f955e08b | ||
![]() |
91e6503503 | ||
![]() |
c7c98c623d | ||
![]() |
80aa847457 | ||
![]() |
f1c981338c | ||
![]() |
d4225a459e | ||
![]() |
75ae37d90f | ||
![]() |
2159115679 | ||
![]() |
0384de9a3c | ||
![]() |
ae2e1fc381 | ||
![]() |
d45993c905 | ||
![]() |
4e6c7b01b6 | ||
![]() |
775ce56d2e | ||
![]() |
d41c466f6e | ||
![]() |
387135ffa5 | ||
![]() |
64b176103e | ||
![]() |
7f88c7d70c | ||
![]() |
1a89ad95e0 | ||
![]() |
376f991db5 | ||
![]() |
623893b528 | ||
![]() |
890f6f35b5 | ||
![]() |
ab4af350dd | ||
![]() |
95bfc4be9a | ||
![]() |
95d9c8fa2b | ||
![]() |
83dd5f51cd | ||
![]() |
5d1dddfac8 | ||
![]() |
50ba88231f | ||
![]() |
221cf12184 | ||
![]() |
681b769a71 | ||
![]() |
27517c15ca | ||
![]() |
56f566e13a | ||
![]() |
6131a40c31 | ||
![]() |
040e652e6a | ||
![]() |
caf0e1d15b | ||
![]() |
9dd8b7cd88 | ||
![]() |
8702a739b0 | ||
![]() |
8104851c08 | ||
![]() |
0e03c48beb | ||
![]() |
3fbf24a1c2 | ||
![]() |
64a966c9a5 | ||
![]() |
18a128b917 | ||
![]() |
cfd263da90 | ||
![]() |
0f4a7f0a04 | ||
![]() |
ae5dd62105 | ||
![]() |
b73ff095e6 | ||
![]() |
4503be110a | ||
![]() |
7fef27e6de | ||
![]() |
d8eabd66ea | ||
![]() |
a62e5f32b8 | ||
![]() |
24fe5bb838 | ||
![]() |
5217acc471 | ||
![]() |
f96d97a637 | ||
![]() |
de38f46a53 | ||
![]() |
8f94607409 | ||
![]() |
88ee3694f7 | ||
![]() |
584307dc54 | ||
![]() |
62fd32afbc | ||
![]() |
bfcfcde71a | ||
![]() |
6ce0945aeb | ||
![]() |
f701479d77 | ||
![]() |
4e93d92e46 | ||
![]() |
ebcdcc6a1e | ||
![]() |
b5cd713e16 | ||
![]() |
0adb8cea91 | ||
![]() |
bce79189e5 | ||
![]() |
8927e0185b | ||
![]() |
df95fad9be | ||
![]() |
e96809a08e | ||
![]() |
7ebc1351fe | ||
![]() |
ee31249d65 | ||
![]() |
a9d6e7f402 | ||
![]() |
296be9135a | ||
![]() |
f24640dec2 | ||
![]() |
64d6e6eded | ||
![]() |
587cd80055 | ||
![]() |
527b7bee3f | ||
![]() |
e1f52d706f | ||
![]() |
2e2e69f07c | ||
![]() |
6a3e4f0857 | ||
![]() |
ff3bdd7f5a | ||
![]() |
1e185d1502 | ||
![]() |
8f9aab407d | ||
![]() |
4cf0ce1b06 | ||
![]() |
8430aa75da | ||
![]() |
f5a47de1d6 | ||
![]() |
1fe322bbac | ||
![]() |
f6da608154 | ||
![]() |
22fc16f4a3 | ||
![]() |
def85a3d37 | ||
![]() |
f638079361 | ||
![]() |
e87ab91d0e | ||
![]() |
fb56602081 | ||
![]() |
2c1d9f2d7b | ||
![]() |
49385959b8 | ||
![]() |
3511c86abd | ||
![]() |
9908580409 | ||
![]() |
5bad23d7be | ||
![]() |
8cde2cd4b2 | ||
![]() |
74db555f78 | ||
![]() |
a1a415a5d1 | ||
![]() |
49053b6ad2 | ||
![]() |
fbfdd95958 | ||
![]() |
2c065da987 | ||
![]() |
6c7281ae88 | ||
![]() |
4bb0da397a | ||
![]() |
6a355b8dff | ||
![]() |
aa1fb63714 | ||
![]() |
c9ce69c1c1 | ||
![]() |
06ee41226d | ||
![]() |
bf634eee66 | ||
![]() |
e606ae5097 | ||
![]() |
ecc40d022d | ||
![]() |
262e8ee999 | ||
![]() |
141315cf42 | ||
![]() |
6fa0d00b8f | ||
![]() |
47339c84b3 | ||
![]() |
692a5081c7 | ||
![]() |
28c3f8d614 | ||
![]() |
fb5d35e43e | ||
![]() |
a4bff61e5b | ||
![]() |
2c4bbf8a00 | ||
![]() |
d2ec38d5fd | ||
![]() |
517e037724 | ||
![]() |
0051d9f76e | ||
![]() |
c0915a3dee | ||
![]() |
4363d4c9ed | ||
![]() |
d7095f7ee1 | ||
![]() |
ebc5f1a01d | ||
![]() |
d6ad41ab3a | ||
![]() |
9c2e55407f | ||
![]() |
7c70659212 | ||
![]() |
5822273c8d | ||
![]() |
001cd83ef8 | ||
![]() |
b48c290e9c | ||
![]() |
327f00e312 | ||
![]() |
b1ae8d1332 | ||
![]() |
38cb8201a1 | ||
![]() |
e3478edeeb | ||
![]() |
69f1931f4f | ||
![]() |
6eb8908a16 | ||
![]() |
88dcd889fa | ||
![]() |
9cd6235947 | ||
![]() |
bcb2853150 | ||
![]() |
ad241f12a3 | ||
![]() |
b29627c92b | ||
![]() |
8518d583d9 | ||
![]() |
81dee38e4a | ||
![]() |
fa6cc9692e | ||
![]() |
c3a92d659e | ||
![]() |
ffed65533b | ||
![]() |
5a393569f0 | ||
![]() |
6cf20a93d0 | ||
![]() |
a2b5fb8374 | ||
![]() |
f4f9200fba | ||
![]() |
52640f08d2 | ||
![]() |
bbb5783b4f | ||
![]() |
cde937a9eb | ||
![]() |
a4ee4e9b17 | ||
![]() |
34a06435cf | ||
![]() |
fad6e7284a | ||
![]() |
29f73b2dbb | ||
![]() |
968725f09f | ||
![]() |
42064df3e0 | ||
![]() |
c980a52244 | ||
![]() |
ed5c50db7d | ||
![]() |
b463428a40 | ||
![]() |
38f279fd2a | ||
![]() |
d3ab4d2f11 | ||
![]() |
1170827f3d | ||
![]() |
838631b057 | ||
![]() |
0a469cfdd1 | ||
![]() |
fc82121604 | ||
![]() |
25444034ab | ||
![]() |
eec1dbe0a0 | ||
![]() |
47e8bdb752 | ||
![]() |
75fc373b51 | ||
![]() |
8a397034fd | ||
![]() |
89476e4479 | ||
![]() |
1b61765df8 | ||
![]() |
40da245d8d | ||
![]() |
1238d8b994 | ||
![]() |
460d202eb0 | ||
![]() |
248e4e5eb9 | ||
![]() |
08299fb808 | ||
![]() |
c06f6145a1 | ||
![]() |
6101f42ae3 | ||
![]() |
9ffd9027fa | ||
![]() |
10995788d1 | ||
![]() |
98bc51a3ec | ||
![]() |
cc9f9b6e8b | ||
![]() |
7f0f48ddac | ||
![]() |
e92046a265 | ||
![]() |
fe00dffb70 | ||
![]() |
a02ddeb722 | ||
![]() |
9b3bc62132 | ||
![]() |
d7b3e7bd69 | ||
![]() |
d3fda57b6d | ||
![]() |
257ebb88f0 | ||
![]() |
9257cdac8f | ||
![]() |
19fddc8da8 | ||
![]() |
44da3fd195 | ||
![]() |
e452c161ba | ||
![]() |
c7c167a058 | ||
![]() |
6f3cdbc165 | ||
![]() |
5b4a3e4288 | ||
![]() |
e783494022 | ||
![]() |
b7ff94900f | ||
![]() |
e761cc76fa | ||
![]() |
96da61f4e4 | ||
![]() |
ca3d62f377 | ||
![]() |
0584ceb157 | ||
![]() |
633b0dd928 | ||
![]() |
cad2f77490 | ||
![]() |
a40448a350 | ||
![]() |
01df596dc7 | ||
![]() |
176b0416cd | ||
![]() |
b0449d59da | ||
![]() |
804222d68a | ||
![]() |
858bca0f7d | ||
![]() |
ac459b84c6 | ||
![]() |
716005fbd2 | ||
![]() |
086dccc177 | ||
![]() |
e13dbe4881 | ||
![]() |
6a16bdf5fd | ||
![]() |
f3b46f50bf | ||
![]() |
14a2ad2b0d | ||
![]() |
fb539865e0 | ||
![]() |
7d92caccf0 | ||
![]() |
2e71eee7b4 | ||
![]() |
507085ee7b | ||
![]() |
4690b273cc | ||
![]() |
335bdb820f | ||
![]() |
b17d9f850e | ||
![]() |
7f8ba75d90 | ||
![]() |
842b951549 | ||
![]() |
f373211281 | ||
![]() |
c5500db9ef | ||
![]() |
729d2da764 | ||
![]() |
2587d7fec8 | ||
![]() |
a6c6f64453 | ||
![]() |
b31bfeebd7 | ||
![]() |
e107d5df6f | ||
![]() |
6e84668884 | ||
![]() |
63d2dcc1f7 | ||
![]() |
0ee6426eb5 | ||
![]() |
ac2cac6edc | ||
![]() |
73682d22d6 | ||
![]() |
bef80037da | ||
![]() |
056b9638ab | ||
![]() |
be94a8e49a | ||
![]() |
d153672f0d | ||
![]() |
9f9581e1f8 | ||
![]() |
7587150f96 | ||
![]() |
e97b06674c | ||
![]() |
e82700a826 | ||
![]() |
05c16e1539 | ||
![]() |
50fa69aca4 | ||
![]() |
cb3001ac3b | ||
![]() |
9bbcb9319c | ||
![]() |
32f371fcb6 | ||
![]() |
16559e83f5 | ||
![]() |
052c8c5372 | ||
![]() |
b0588321e0 | ||
![]() |
574ab7d696 | ||
![]() |
336b908e8f | ||
![]() |
b41dd2780e | ||
![]() |
7e99d7515f | ||
![]() |
c9de592832 | ||
![]() |
69ac7b9bcf | ||
![]() |
8268607a56 | ||
![]() |
c33e9245bf | ||
![]() |
4d5166d568 | ||
![]() |
fdc8060071 | ||
![]() |
e139ce77ee | ||
![]() |
ed6f2e40cf | ||
![]() |
05f57249d6 | ||
![]() |
e91befabc0 | ||
![]() |
2e641b0e30 | ||
![]() |
7e36986a26 | ||
![]() |
586db3bc5e | ||
![]() |
51fd19c315 | ||
![]() |
426ad30a52 | ||
![]() |
111ed38cce | ||
![]() |
e07128a145 | ||
![]() |
610fa075f6 | ||
![]() |
5e75d84920 | ||
![]() |
4d97a825d9 | ||
![]() |
bac739a6d9 | ||
![]() |
d935dcd350 | ||
![]() |
be2061b74d | ||
![]() |
2aa2086dfb | ||
![]() |
a89d4ee434 | ||
![]() |
cd5d762cbc | ||
![]() |
a96ab9a9a4 | ||
![]() |
f0a1aed029 | ||
![]() |
7b56ad9dad | ||
![]() |
e05f365e6a | ||
![]() |
c15e94f759 | ||
![]() |
d93ec0d5c7 | ||
![]() |
74cf5373b9 | ||
![]() |
4ddc034e9c | ||
![]() |
061dc04755 | ||
![]() |
0e4597131b | ||
![]() |
57f77c4657 | ||
![]() |
89d6e422f5 | ||
![]() |
520f92503f | ||
![]() |
4cef4adc7e | ||
![]() |
e97ff3d671 | ||
![]() |
97e96d02f2 | ||
![]() |
654ee4e62e | ||
![]() |
87fe1be1ed | ||
![]() |
4d7d3afc7d | ||
![]() |
7bca5bf40e | ||
![]() |
158e83c425 | ||
![]() |
fa0ccff5b2 | ||
![]() |
a0505aa8e9 | ||
![]() |
86677ee6b4 | ||
![]() |
eb91ac0c3c | ||
![]() |
a21fb36cd2 | ||
![]() |
28209bb474 | ||
![]() |
376efcde27 | ||
![]() |
4684d19953 | ||
![]() |
4bea504690 | ||
![]() |
90f4ccfb94 | ||
![]() |
d292f71007 | ||
![]() |
4a45a77753 | ||
![]() |
ef28ae8117 | ||
![]() |
b8b0b61e67 | ||
![]() |
41c1b711c2 | ||
![]() |
8ab251c5f7 | ||
![]() |
659c7cdbd8 | ||
![]() |
ef9d8c64fc | ||
![]() |
e6927a196f | ||
![]() |
729e5ee0e1 | ||
![]() |
a3f214b6ba | ||
![]() |
a2f0a9687d | ||
![]() |
820920839d | ||
![]() |
0d5d8f7c80 | ||
![]() |
bf198f37db | ||
![]() |
c6af2044ce | ||
![]() |
a9b331c5fd | ||
![]() |
cb88ffff79 | ||
![]() |
bcf17bfdc0 | ||
![]() |
110ef17ed8 | ||
![]() |
348d07757b | ||
![]() |
eaeda47690 | ||
![]() |
fdf330276e | ||
![]() |
dace3dc803 | ||
![]() |
70d48b39f3 | ||
![]() |
d9f5bc7681 | ||
![]() |
52aa78acab | ||
![]() |
b73ec76146 | ||
![]() |
70e49a61fa | ||
![]() |
7904a3efb7 | ||
![]() |
717a4951fd | ||
![]() |
a3b4349b1c | ||
![]() |
4b74cd5677 | ||
![]() |
6d554bace1 | ||
![]() |
c4367818b7 | ||
![]() |
ebdddc4fe4 | ||
![]() |
bac0dbb70b | ||
![]() |
0a7412424d | ||
![]() |
d5601b7ec0 | ||
![]() |
b79d88d5ef | ||
![]() |
851d9cc313 | ||
![]() |
40ef375c15 | ||
![]() |
de32addf76 | ||
![]() |
1e541b688d | ||
![]() |
c05bfb894a | ||
![]() |
279e269a66 | ||
![]() |
8490b65bcc | ||
![]() |
1234634ba3 | ||
![]() |
3d2d9cb3a2 | ||
![]() |
7740961697 | ||
![]() |
22c77e7be5 | ||
![]() |
6566e36141 | ||
![]() |
a4e5d36a02 | ||
![]() |
54a0da8151 | ||
![]() |
dc525783ee | ||
![]() |
a5ae056c9b | ||
![]() |
e0c87fc556 | ||
![]() |
fb38aacde4 | ||
![]() |
564f3b9170 | ||
![]() |
9cb14e2815 | ||
![]() |
54c023523f | ||
![]() |
97d068c3bb | ||
![]() |
f090537ef4 | ||
![]() |
3f01a9e1e2 | ||
![]() |
be7bf5288b | ||
![]() |
71d7aa3fb2 | ||
![]() |
1b8c4bb1a5 | ||
![]() |
fddda75f75 | ||
![]() |
aa7e2594e2 | ||
![]() |
5236f4e58d | ||
![]() |
916ea79e57 | ||
![]() |
b855222ee1 | ||
![]() |
fc31195fa0 | ||
![]() |
70cb27bf0a | ||
![]() |
2a744a3a83 | ||
![]() |
be56707a8a | ||
![]() |
a74404170d | ||
![]() |
2e544326e5 | ||
![]() |
d42c13a9c6 | ||
![]() |
020696fb17 | ||
![]() |
06bf3e27d3 | ||
![]() |
3b17f9d6ec | ||
![]() |
9c8b43f602 | ||
![]() |
70f052cb5c | ||
![]() |
e5c10fcd93 | ||
![]() |
9eb377703e | ||
![]() |
4c63dad309 | ||
![]() |
45e52aa985 | ||
![]() |
6066d00c5e | ||
![]() |
59a10a8127 | ||
![]() |
6dc8edea88 | ||
![]() |
ef1ee8e0c0 | ||
![]() |
1428b26703 | ||
![]() |
63b841c496 | ||
![]() |
208f4291d6 | ||
![]() |
750d08ec01 | ||
![]() |
8d665aeac4 | ||
![]() |
a0f983f05d | ||
![]() |
1df922ef16 | ||
![]() |
beed820602 | ||
![]() |
b6722fdd84 | ||
![]() |
eb47fb5501 | ||
![]() |
aacf7ba275 | ||
![]() |
400392655e | ||
![]() |
713985f259 | ||
![]() |
664280ccce | ||
![]() |
9fe6c5c3a9 | ||
![]() |
ab5098a036 | ||
![]() |
b092bb6848 | ||
![]() |
17ded12375 | ||
![]() |
118149c539 | ||
![]() |
57da323cea | ||
![]() |
ebe2ba401d | ||
![]() |
a67443c195 | ||
![]() |
2e0d36c4d9 | ||
![]() |
db4b621631 | ||
![]() |
a91958bfe1 | ||
![]() |
5395208b00 | ||
![]() |
d909010f08 | ||
![]() |
5c7b65163e | ||
![]() |
e4e4efcba7 | ||
![]() |
9f18d0ad45 | ||
![]() |
2de3894d67 | ||
![]() |
03c6a4e18e | ||
![]() |
f9ab8d3b35 | ||
![]() |
14f87f5aee | ||
![]() |
bb569b4e78 | ||
![]() |
ef63ec40d9 | ||
![]() |
761a6a4264 | ||
![]() |
8139ecfd39 | ||
![]() |
fb09f67899 | ||
![]() |
f075384b44 | ||
![]() |
b8e8bf3dd4 | ||
![]() |
d690b34ee0 | ||
![]() |
e24b40de29 | ||
![]() |
bf3ffc29a9 | ||
![]() |
6581cff8dc | ||
![]() |
5c3ae44021 | ||
![]() |
2b341afcae | ||
![]() |
7f4cfc0b76 | ||
![]() |
b2327d6fde | ||
![]() |
f964dd5935 | ||
![]() |
4ecd5ada06 | ||
![]() |
f770f0444a | ||
![]() |
39d1c051cf | ||
![]() |
5622e13802 | ||
![]() |
d6285cc851 | ||
![]() |
777d8b4609 | ||
![]() |
edb9264d78 | ||
![]() |
6b708c5ed3 | ||
![]() |
1dd2386fa5 | ||
![]() |
e6164eb1ab | ||
![]() |
bd01b821ec | ||
![]() |
b44ca770a5 | ||
![]() |
9093ac5901 | ||
![]() |
755da317ea | ||
![]() |
6834c70bae | ||
![]() |
1297c0911c | ||
![]() |
ebcf4e2d81 | ||
![]() |
bd3a2306d6 | ||
![]() |
27666da4e9 | ||
![]() |
70f7b614e6 | ||
![]() |
9bf4ce25b2 | ||
![]() |
d51848cdc0 | ||
![]() |
7d86ee32af | ||
![]() |
70c02a1c82 | ||
![]() |
39637fc4aa | ||
![]() |
1de7a490b4 | ||
![]() |
6d4aa76405 | ||
![]() |
27ae4f6b1e | ||
![]() |
d6e733c56f | ||
![]() |
7497e0f6b9 | ||
![]() |
aa6e96e54d | ||
![]() |
3d173a13ab | ||
![]() |
bdf2e29843 | ||
![]() |
7beb8a0929 | ||
![]() |
8af0259671 | ||
![]() |
67953c98a9 | ||
![]() |
527c533958 | ||
![]() |
544ca8d008 | ||
![]() |
bd02c78966 | ||
![]() |
9e311241b3 | ||
![]() |
e228e18f04 | ||
![]() |
e2bea3aee3 | ||
![]() |
ba9b5c50d2 | ||
![]() |
61834581d5 | ||
![]() |
08beaf81d5 | ||
![]() |
1276419ec6 | ||
![]() |
ef9631ae24 | ||
![]() |
86079a936e | ||
![]() |
c6acf2f7f6 | ||
![]() |
28b7c3c208 | ||
![]() |
75c8cd9967 | ||
![]() |
4fb5dce5e7 | ||
![]() |
b8e7506de4 | ||
![]() |
0560ac2a95 | ||
![]() |
131ebf0480 | ||
![]() |
80420a99f5 | ||
![]() |
6a70369a77 | ||
![]() |
fb83069975 | ||
![]() |
f61ecadf76 | ||
![]() |
f040c4e593 | ||
![]() |
c2a47ca4b1 | ||
![]() |
a283b815ef | ||
![]() |
3dd4583ea8 | ||
![]() |
bf79b252ad | ||
![]() |
a2ad62b310 | ||
![]() |
4b9a8f3409 | ||
![]() |
802bd7fb0d | ||
![]() |
320298e3ff | ||
![]() |
5e5059b2e7 | ||
![]() |
d6d7528668 | ||
![]() |
3f8c74c4af | ||
![]() |
0a1b810da7 | ||
![]() |
25fb9fb185 | ||
![]() |
c547128238 | ||
![]() |
99b5e25731 | ||
![]() |
20e724da46 | ||
![]() |
03838421bc | ||
![]() |
b9cf517cd1 | ||
![]() |
f7f78d80b7 | ||
![]() |
e63b820c07 | ||
![]() |
2ac6a02e31 | ||
![]() |
6e79b771ec | ||
![]() |
37caf6a64a | ||
![]() |
198354d07d | ||
![]() |
eec9716ffa | ||
![]() |
64d0c7fae6 | ||
![]() |
02e81f7ab5 | ||
![]() |
85cf931d0a | ||
![]() |
c54d26ed19 | ||
![]() |
cffe9fa354 | ||
![]() |
46b0776714 | ||
![]() |
929b25a969 | ||
![]() |
3c2fac3d28 | ||
![]() |
9a165e87fd | ||
![]() |
95c4e77ae4 | ||
![]() |
ba3696566f | ||
![]() |
6907b91420 | ||
![]() |
227934a7f0 | ||
![]() |
089a8c0498 | ||
![]() |
92fa978735 | ||
![]() |
8135de49f0 | ||
![]() |
ccfa14b9b7 | ||
![]() |
6589369e1b | ||
![]() |
9c2c74ad2b | ||
![]() |
b7c118afa3 | ||
![]() |
e9b5f8d9f8 | ||
![]() |
e48294a74b | ||
![]() |
50c5a23de8 | ||
![]() |
7d676a75a8 | ||
![]() |
544e8db722 | ||
![]() |
ba066af664 | ||
![]() |
c4286d0a48 | ||
![]() |
1c535e6ff1 | ||
![]() |
0b9ea5c60f | ||
![]() |
0fa3c3188d | ||
![]() |
ebcb2cf694 | ||
![]() |
8dc15352ef | ||
![]() |
403de42031 | ||
![]() |
b08a5e62d8 | ||
![]() |
1f62b6d0d4 | ||
![]() |
c751fe7520 | ||
![]() |
978bb3c339 | ||
![]() |
3e389a3140 | ||
![]() |
0dbd598116 | ||
![]() |
46ecdefde8 | ||
![]() |
e8ea373eb2 | ||
![]() |
01d10da061 | ||
![]() |
0aad31b4bc | ||
![]() |
2f599ca1d3 | ||
![]() |
162626209c | ||
![]() |
cd8f99d2c3 | ||
![]() |
6968e228e1 | ||
![]() |
b7d310ef90 | ||
![]() |
1c3b85249c | ||
![]() |
bf3b110804 | ||
![]() |
7d1f931234 | ||
![]() |
147a8774c6 | ||
![]() |
406f8daa12 | ||
![]() |
0a4a06b991 | ||
![]() |
41e842a9e6 | ||
![]() |
1fb3316436 | ||
![]() |
2f26d07480 | ||
![]() |
360fc081bb | ||
![]() |
4cae338479 | ||
![]() |
9ace199422 | ||
![]() |
f42e5bf1e5 | ||
![]() |
5863060585 | ||
![]() |
e466158ce2 | ||
![]() |
38156123d4 | ||
![]() |
ade951a600 | ||
![]() |
48b59c8e24 | ||
![]() |
b3a13cec17 | ||
![]() |
ae3e2a7063 | ||
![]() |
48d83e166b | ||
![]() |
29e9d7d793 | ||
![]() |
dcbc0ea2e5 | ||
![]() |
c527b274b6 | ||
![]() |
5892941d8a | ||
![]() |
b653e44f65 | ||
![]() |
e75534c0f2 | ||
![]() |
0e93f7eba5 | ||
![]() |
7817315f8b | ||
![]() |
ba18258750 | ||
![]() |
23381f7d17 | ||
![]() |
665863e395 | ||
![]() |
d9e3895f34 | ||
![]() |
f06e2c1089 | ||
![]() |
dd6aa2f775 | ||
![]() |
c6b9e2b544 | ||
![]() |
240d5b9da2 | ||
![]() |
5b344963b9 | ||
![]() |
b10e7abbe8 | ||
![]() |
01c2fe508e | ||
![]() |
ee31fdc650 | ||
![]() |
fa7b90a584 | ||
![]() |
37c2051e01 | ||
![]() |
3561935e1b | ||
![]() |
7669679fb1 | ||
![]() |
2e44c18cdb | ||
![]() |
86da578774 | ||
![]() |
46f778111c | ||
![]() |
7dfcc7f47b | ||
![]() |
39b35c090b | ||
![]() |
ee4e026ba2 | ||
![]() |
de6ba3489a | ||
![]() |
6381093386 | ||
![]() |
fd6bfd02ce | ||
![]() |
1da652ba4d | ||
![]() |
9a4190bedf | ||
![]() |
561db8607a | ||
![]() |
7f9a0204b5 | ||
![]() |
32224f187d | ||
![]() |
d91fa99e77 | ||
![]() |
3f94fc2618 | ||
![]() |
e79c45c98d | ||
![]() |
400da7bbc5 | ||
![]() |
bb814da95b | ||
![]() |
fad3df1e39 | ||
![]() |
1b1b57eb6a | ||
![]() |
57a5a4147b | ||
![]() |
1041504cb1 | ||
![]() |
26b40e06f8 | ||
![]() |
df8235de13 | ||
![]() |
12e45624db | ||
![]() |
37237dfcf6 | ||
![]() |
da3695e3a4 | ||
![]() |
24c53e78a7 | ||
![]() |
275bd96ba8 | ||
![]() |
01d448ecde | ||
![]() |
3cdd38cb70 | ||
![]() |
f184e6b162 | ||
![]() |
55a6dca373 | ||
![]() |
5517c049b8 | ||
![]() |
86f83f2bc4 | ||
![]() |
557abbc17e | ||
![]() |
e0293db16d | ||
![]() |
fbb2da42dc | ||
![]() |
2d841e7167 | ||
![]() |
f214fe1b3e | ||
![]() |
e5fe515b69 | ||
![]() |
dfb88ebf83 | ||
![]() |
789abb3bbb | ||
![]() |
273c474e3f | ||
![]() |
b262ec4b32 | ||
![]() |
c05de3d57f | ||
![]() |
55c4c690ef | ||
![]() |
e10a2391c4 | ||
![]() |
9b244d0265 | ||
![]() |
cfc1ca45fc | ||
![]() |
1c4e3f682e | ||
![]() |
75b22e8684 | ||
![]() |
ca2cb694d0 | ||
![]() |
cea34211b6 | ||
![]() |
d252d040bf | ||
![]() |
43c88ae0f0 | ||
![]() |
93be4e98d5 | ||
![]() |
659cd3e9d5 | ||
![]() |
2c3eaadbce | ||
![]() |
1947d67e69 | ||
![]() |
35dcc54dc8 | ||
![]() |
48796e6961 | ||
![]() |
164418880a | ||
![]() |
fbca412d30 | ||
![]() |
70347bb8f3 | ||
![]() |
eaf11ea134 | ||
![]() |
a59f8cd1b1 | ||
![]() |
e9affbc1cf | ||
![]() |
aa8789ae31 | ||
![]() |
5c310c51d4 | ||
![]() |
cf3fa50b55 | ||
![]() |
7f933d373f | ||
![]() |
ece94379d8 | ||
![]() |
aa714bded3 | ||
![]() |
ecfae9dadd | ||
![]() |
69c04a209a | ||
![]() |
e4ec52ed29 | ||
![]() |
50aedc1094 | ||
![]() |
062f8e5a73 | ||
![]() |
c813c02025 | ||
![]() |
28f45d8f15 | ||
![]() |
8e339789fa | ||
![]() |
dec17a3b9b | ||
![]() |
6b60501dc7 | ||
![]() |
0e78f32009 | ||
![]() |
b13ec571f8 | ||
![]() |
9f5e6d1969 | ||
![]() |
b2e0a8c884 | ||
![]() |
e47b105185 | ||
![]() |
8bd82f5c69 | ||
![]() |
e528a587cc | ||
![]() |
1a526ac31e | ||
![]() |
22e56f09ba | ||
![]() |
af0eafbb3b | ||
![]() |
8e57d4e791 | ||
![]() |
b2a9cf4709 | ||
![]() |
677cfb7a1e | ||
![]() |
fb9d750684 | ||
![]() |
b8469946a8 | ||
![]() |
beffde1051 | ||
![]() |
71c58c4b05 | ||
![]() |
02e67d25b4 | ||
![]() |
d208ab1e12 | ||
![]() |
55075619c1 | ||
![]() |
7dce57b9f7 | ||
![]() |
a0c74025e3 | ||
![]() |
31bea6a361 | ||
![]() |
5894060dc5 | ||
![]() |
b787983e42 | ||
![]() |
7e0aa7136a | ||
![]() |
56204933b0 | ||
![]() |
49be87fe37 | ||
![]() |
03f071fd27 | ||
![]() |
34c42c4339 | ||
![]() |
b45bd66573 | ||
![]() |
3b2bc292d8 | ||
![]() |
30185d560c | ||
![]() |
6e614eda5e | ||
![]() |
164755c755 | ||
![]() |
6d39dfeb3b | ||
![]() |
999b36473c | ||
![]() |
8b57967836 | ||
![]() |
ff71b04848 | ||
![]() |
67d03c11b9 | ||
![]() |
533be7e96e | ||
![]() |
4ed56e4603 | ||
![]() |
45848f5e34 | ||
![]() |
cf619d9d31 | ||
![]() |
de87efc291 | ||
![]() |
889fe5890d | ||
![]() |
958acd8a36 | ||
![]() |
381a503947 | ||
![]() |
b7126030d1 | ||
![]() |
13d934dc6e | ||
![]() |
926e746005 | ||
![]() |
94c07839a4 | ||
![]() |
277e668e07 | ||
![]() |
10440ec820 | ||
![]() |
02c1d496d6 | ||
![]() |
98ab79ad5a | ||
![]() |
e1fef59e82 | ||
![]() |
32201dd034 | ||
![]() |
670b6d3629 | ||
![]() |
54d90a4c4b | ||
![]() |
9bfc92cf79 | ||
![]() |
a12ec00827 | ||
![]() |
8cc0336338 | ||
![]() |
bad7caa8b9 | ||
![]() |
251fc582e9 | ||
![]() |
245af65841 | ||
![]() |
ee7492cf52 | ||
![]() |
8e5c2a2b14 | ||
![]() |
1343e4c99f | ||
![]() |
89cb1211e7 | ||
![]() |
04bb7d4893 | ||
![]() |
1fafb9ace6 | ||
![]() |
ae51619243 | ||
![]() |
7ac101d84e | ||
![]() |
2c18f6268b | ||
![]() |
7d212f6e80 | ||
![]() |
3d8cd0f0d6 | ||
![]() |
3f719a21e0 | ||
![]() |
7a75d3f41b | ||
![]() |
1ddad84985 | ||
![]() |
bcdbc975d6 | ||
![]() |
a61ea3555a | ||
![]() |
2de546fd52 | ||
![]() |
d6894d3c64 | ||
![]() |
bb1725c7dd | ||
![]() |
6f684f8070 | ||
![]() |
7712230300 | ||
![]() |
7e4c5af158 | ||
![]() |
2dc3019083 | ||
![]() |
b5a85caa72 | ||
![]() |
bb9b438aa6 | ||
![]() |
3089b049cf | ||
![]() |
5bea5e75c0 | ||
![]() |
7906d8fef1 | ||
![]() |
30853e963e | ||
![]() |
1379c039b8 | ||
![]() |
37c21e518d | ||
![]() |
e215e11417 | ||
![]() |
2374506a20 | ||
![]() |
1c4d19198f | ||
![]() |
e77be6a2ed | ||
![]() |
1fdf1ef337 | ||
![]() |
f5cc5fbaa3 | ||
![]() |
a0631413d6 | ||
![]() |
8ce4434ba9 | ||
![]() |
f6a50ee7c6 | ||
![]() |
beff45a835 | ||
![]() |
dfa1f29809 | ||
![]() |
2a57f9d6e5 | ||
![]() |
02871e1e22 | ||
![]() |
9cd40e96f4 | ||
![]() |
bf9051e44d | ||
![]() |
ebb39b13f0 | ||
![]() |
4f14e0f425 | ||
![]() |
e7cb358536 | ||
![]() |
a85792e327 | ||
![]() |
f5df910894 | ||
![]() |
80b47fa287 | ||
![]() |
1aa76f8483 | ||
![]() |
de5d360d52 | ||
![]() |
f0ad92e542 | ||
![]() |
0b7ffa31d1 | ||
![]() |
b452816a29 | ||
![]() |
d1d09ac6ac | ||
![]() |
66240188c7 | ||
![]() |
d1f285113d | ||
![]() |
56dfc71bb9 | ||
![]() |
a8f27f79dd | ||
![]() |
2c702eb568 | ||
![]() |
63a58ccc38 | ||
![]() |
4b0027797a | ||
![]() |
66d6d29c23 | ||
![]() |
fbb3a069cd | ||
![]() |
a37796d0cf | ||
![]() |
0b4c860354 | ||
![]() |
a4a08aa667 | ||
![]() |
c24bfd4d2b | ||
![]() |
ed480f62e3 | ||
![]() |
66aa7319ab | ||
![]() |
4146955f4a | ||
![]() |
57504b7ee6 | ||
![]() |
364df5c050 | ||
![]() |
f83185bfe4 | ||
![]() |
db02d68a5a | ||
![]() |
9a18954686 | ||
![]() |
edcb62476b | ||
![]() |
3a82b7806a | ||
![]() |
51b1528fee | ||
![]() |
defa80d05a | ||
![]() |
abd54eeb3a | ||
![]() |
2f7bb01f34 | ||
![]() |
25e1177198 | ||
![]() |
ab8a1cfded | ||
![]() |
fa5121082d | ||
![]() |
48e785f7b6 | ||
![]() |
0cc22017de | ||
![]() |
3584f732a7 | ||
![]() |
476beacd7f | ||
![]() |
69c6d68219 | ||
![]() |
24d8a50f01 | ||
![]() |
2df1894683 | ||
![]() |
3f03cbf66c | ||
![]() |
b3daf0efc3 | ||
![]() |
46c0ab943f | ||
![]() |
2b57b80656 | ||
![]() |
0b1b9de3cc | ||
![]() |
20c46278dc | ||
![]() |
70cbdbf23b | ||
![]() |
6003122b06 | ||
![]() |
8ca97924be | ||
![]() |
2be0ba9f72 | ||
![]() |
f0d86130ec | ||
![]() |
ed236460b5 | ||
![]() |
a4f7c5ddcb | ||
![]() |
4fbb814e5b | ||
![]() |
0f635d1bb2 | ||
![]() |
0d48aea308 | ||
![]() |
06a3fff2bc | ||
![]() |
c28f19c9cf | ||
![]() |
da87542a52 | ||
![]() |
23ba3be68f | ||
![]() |
f3fd0fcf72 | ||
![]() |
72706a335d | ||
![]() |
0a0d462938 | ||
![]() |
74a99cf330 | ||
![]() |
5753c83618 | ||
![]() |
550a74347c | ||
![]() |
e428a8a008 | ||
![]() |
001ab88fff | ||
![]() |
d3cf85b9e9 | ||
![]() |
91c722feff | ||
![]() |
871e22e3a3 | ||
![]() |
bf3b2249c5 | ||
![]() |
6613104b4f | ||
![]() |
0028fde2fd | ||
![]() |
ad527fe97c | ||
![]() |
9da11f29c7 | ||
![]() |
c240fa1883 | ||
![]() |
bb33ac5e9e | ||
![]() |
30f200ad39 | ||
![]() |
5321ff1f20 | ||
![]() |
c4a939dbcc | ||
![]() |
3f05fe45bb | ||
![]() |
dfd844124d | ||
![]() |
d4febbc40f | ||
![]() |
dc36e8566a | ||
![]() |
87fa118de0 | ||
![]() |
35c3d5c0b5 | ||
![]() |
9e46afafd7 | ||
![]() |
56acd4f320 | ||
![]() |
e2456f4b3f | ||
![]() |
2bbeb8ffe0 | ||
![]() |
5e188c0203 | ||
![]() |
8b637214b4 | ||
![]() |
fcaaf7ce03 | ||
![]() |
522ada88ea | ||
![]() |
eede5595e9 | ||
![]() |
c1fc8b2dac | ||
![]() |
28622d700d | ||
![]() |
a079c310b4 | ||
![]() |
278f6da16a | ||
![]() |
5369e0be03 | ||
![]() |
8699b6931c | ||
![]() |
45e39d04ae | ||
![]() |
e46353cee8 | ||
![]() |
65816a434c | ||
![]() |
e3104d34fa | ||
![]() |
891bd2de7f | ||
![]() |
805e3d51e8 | ||
![]() |
f1f9a076c9 | ||
![]() |
55cc49cd88 | ||
![]() |
d52260468c | ||
![]() |
aacd362203 | ||
![]() |
38a651c42a | ||
![]() |
55cc93e5e9 | ||
![]() |
9ee21f081f | ||
![]() |
bfbdd6e198 | ||
![]() |
1e9e347f15 | ||
![]() |
782dbee3a0 | ||
![]() |
316ee72177 | ||
![]() |
f88cf69173 | ||
![]() |
e9758d5224 | ||
![]() |
5456d5eafa | ||
![]() |
dab4b1253a | ||
![]() |
34bc4020c9 | ||
![]() |
ab871d67fc | ||
![]() |
371745b6dc | ||
![]() |
991a46c4f0 | ||
![]() |
eb5bdc48aa | ||
![]() |
3634dfbcf8 | ||
![]() |
57ad485913 | ||
![]() |
ceaade29a6 | ||
![]() |
9a4d410f66 | ||
![]() |
34f353f399 | ||
![]() |
1d8765100c | ||
![]() |
5bdb57a392 | ||
![]() |
0a18c819d4 | ||
![]() |
982ea84906 | ||
![]() |
68c233005e | ||
![]() |
62cc4a7a54 | ||
![]() |
6d3e5b0a1b | ||
![]() |
c4d13b5802 | ||
![]() |
c263d8e8f1 | ||
![]() |
2a9e6f7a58 | ||
![]() |
c02813623d | ||
![]() |
1b5b07a020 | ||
![]() |
8b16cd99dc | ||
![]() |
20fc065567 | ||
![]() |
802e389198 | ||
![]() |
72a4ff0fca | ||
![]() |
e22769ca63 | ||
![]() |
d661f87f63 | ||
![]() |
748b27c680 | ||
![]() |
6a04e95f69 | ||
![]() |
9e9b9ae631 | ||
![]() |
a47623dbaf | ||
![]() |
657c41ab37 | ||
![]() |
4548cf08c7 | ||
![]() |
e3ce573fbb | ||
![]() |
5e1543bad5 | ||
![]() |
282e6f453f | ||
![]() |
a4f60c48ea | ||
![]() |
f3f5227776 | ||
![]() |
19bb29d5cd | ||
![]() |
8cad12b154 | ||
![]() |
384d381acf | ||
![]() |
834352130c | ||
![]() |
b0c8ade241 | ||
![]() |
a33082235b | ||
![]() |
ec6d01f7a5 | ||
![]() |
1ce6466ef8 | ||
![]() |
f677ed8798 | ||
![]() |
12fa844c7f | ||
![]() |
fd3df1ec58 | ||
![]() |
24b8c358cc | ||
![]() |
d58706a34b | ||
![]() |
3168602610 | ||
![]() |
756c80690d | ||
![]() |
c5dbd7a6fb | ||
![]() |
9318c2c0bc | ||
![]() |
e431a658cc | ||
![]() |
b97fa9e3b9 | ||
![]() |
1b0ddd6df6 | ||
![]() |
8a5c782425 | ||
![]() |
aaa6599283 | ||
![]() |
daf54a334f | ||
![]() |
183d432f84 | ||
![]() |
e1853583b0 | ||
![]() |
f156f05b37 | ||
![]() |
b03d4c7646 | ||
![]() |
1ef12d2cbc | ||
![]() |
fa9a5cc247 | ||
![]() |
35124023f0 | ||
![]() |
0d8688515c | ||
![]() |
f51207fc32 | ||
![]() |
64ee8eab2f | ||
![]() |
2224540b71 | ||
![]() |
fcc0cb7293 | ||
![]() |
fd4c9a1758 | ||
![]() |
ac1b701000 | ||
![]() |
a3143ec512 | ||
![]() |
39c682dc07 | ||
![]() |
eeb63693c9 | ||
![]() |
32186e0de1 | ||
![]() |
023aeea7ea | ||
![]() |
a27daaebe9 | ||
![]() |
51851ff15a | ||
![]() |
490f59451b | ||
![]() |
5160ff9793 | ||
![]() |
fca98b411e | ||
![]() |
2f7396e2aa | ||
![]() |
9677631bb2 | ||
![]() |
0565118a01 | ||
![]() |
24767f62c7 | ||
![]() |
fdaf419a7e | ||
![]() |
c2a86704eb | ||
![]() |
8fbb31a928 | ||
![]() |
ab41a708e9 | ||
![]() |
5d5915c5d6 | ||
![]() |
562d81e246 | ||
![]() |
bddffbce50 | ||
![]() |
6992ac6aa9 | ||
![]() |
dddd6f5503 | ||
![]() |
71fc785753 | ||
![]() |
bc3ae34c26 | ||
![]() |
8361d15a70 | ||
![]() |
52b3057640 | ||
![]() |
074b682312 | ||
![]() |
f7e554a3c1 | ||
![]() |
5b020bb8d2 | ||
![]() |
6388d19f7a | ||
![]() |
5573a84335 | ||
![]() |
a1f5ddede8 | ||
![]() |
481b6c7cec | ||
![]() |
bc4192e7d1 | ||
![]() |
440a23a054 | ||
![]() |
785577b2e8 | ||
![]() |
06cfc3113a | ||
![]() |
ea9de1bcf1 | ||
![]() |
6c308116d6 | ||
![]() |
6834e563a8 | ||
![]() |
938499706c | ||
![]() |
42c9186e91 | ||
![]() |
60ac1ddbb9 | ||
![]() |
a4277706f2 | ||
![]() |
35b2033949 | ||
![]() |
20c1139632 | ||
![]() |
d04b54140c | ||
![]() |
89a31443a5 | ||
![]() |
6b3ec52ed4 | ||
![]() |
202b88632c | ||
![]() |
8bcc40a182 | ||
![]() |
24381ad5dc | ||
![]() |
a4bd2d687e | ||
![]() |
db0f7649d1 | ||
![]() |
6454df57bf | ||
![]() |
b589b7a5dc | ||
![]() |
4bf0d834a0 | ||
![]() |
68e0c21eb0 | ||
![]() |
d5ec762954 | ||
![]() |
7bb1982c48 | ||
![]() |
f956073f4a | ||
![]() |
ae30fef641 | ||
![]() |
75390693b9 | ||
![]() |
43b473dc53 | ||
![]() |
30acfdd3f1 | ||
![]() |
e87575240d | ||
![]() |
39fa02dcb1 | ||
![]() |
7e84863beb | ||
![]() |
2a4fe4dceb | ||
![]() |
ef15de18a9 | ||
![]() |
2163015d06 | ||
![]() |
3b38ac0f9b | ||
![]() |
6f30ceea38 | ||
![]() |
f51d2be303 | ||
![]() |
9bd0bee2f6 | ||
![]() |
a60a4babf6 | ||
![]() |
a03315102a | ||
![]() |
df801d17e1 | ||
![]() |
d3c13f6c93 | ||
![]() |
fe7aa10d2c | ||
![]() |
17a581495c | ||
![]() |
64180b5668 | ||
![]() |
81aaadb2a3 | ||
![]() |
b1110f7291 | ||
![]() |
cb9e5b5ee3 | ||
![]() |
af99cbccd9 | ||
![]() |
97639508cb | ||
![]() |
b269af7572 | ||
![]() |
1987dccf48 | ||
![]() |
d92214d412 | ||
![]() |
751c2ac54b | ||
![]() |
6aca09d485 | ||
![]() |
56ce267f89 | ||
![]() |
ef6690905e | ||
![]() |
2d559d330d | ||
![]() |
95ec520f13 | ||
![]() |
8069c2eb6a | ||
![]() |
9a33f191a7 | ||
![]() |
dd83364326 | ||
![]() |
977594fece | ||
![]() |
cd6e7d9563 | ||
![]() |
f4013b1343 | ||
![]() |
09e419aeee | ||
![]() |
d7160de9f1 | ||
![]() |
ded8f865d8 | ||
![]() |
1e95d22e1a | ||
![]() |
49ff1984f0 | ||
![]() |
f7fa110afe | ||
![]() |
cbdb45473a | ||
![]() |
42b5ac6aff | ||
![]() |
ae17a604d0 | ||
![]() |
933cbe4594 | ||
![]() |
1e9ac63428 | ||
![]() |
c99668b355 | ||
![]() |
6cf0b851b7 | ||
![]() |
d252a1dcda | ||
![]() |
fa5df5d28e | ||
![]() |
4b47f4929e | ||
![]() |
e44b918af2 | ||
![]() |
a4b268cdae | ||
![]() |
d9ae4322ea | ||
![]() |
a316521ea6 | ||
![]() |
a214536a51 | ||
![]() |
acca5be585 | ||
![]() |
b622b3fc6a | ||
![]() |
63953b85e9 | ||
![]() |
6c0e0755b9 | ||
![]() |
8e7a3d309f | ||
![]() |
09a9ab7a34 | ||
![]() |
c11ce4e06f | ||
![]() |
8650af05f7 | ||
![]() |
25f88b7ae9 | ||
![]() |
e75f48d148 | ||
![]() |
d8e27600be | ||
![]() |
9e31429732 | ||
![]() |
1e0020b56b | ||
![]() |
79e6b1f5dd | ||
![]() |
5a292426c9 | ||
![]() |
d2df1b0fc9 | ||
![]() |
fec9e54049 | ||
![]() |
ea089de3b3 | ||
![]() |
172b37239f | ||
![]() |
388e5b56de | ||
![]() |
532d5c1744 | ||
![]() |
54af13e4b8 | ||
![]() |
d65a118d8a | ||
![]() |
af3d161f66 | ||
![]() |
d3482a4aef | ||
![]() |
3600e5a8fb | ||
![]() |
3afee66aaa | ||
![]() |
110c5c392c | ||
![]() |
db4519a644 | ||
![]() |
450fb877f6 | ||
![]() |
b44f8383e4 | ||
![]() |
5a84cc835a | ||
![]() |
529cc04fd1 | ||
![]() |
b7fec4d355 | ||
![]() |
77559332bc | ||
![]() |
321adb5df2 | ||
![]() |
09acb134b7 | ||
![]() |
3d5b66c2b7 | ||
![]() |
41650f20f4 | ||
![]() |
bd45a804a7 | ||
![]() |
3d6b555deb | ||
![]() |
8681cad77c | ||
![]() |
28ea67f252 | ||
![]() |
1255ecf86e | ||
![]() |
2c9555015b | ||
![]() |
391020a2b0 | ||
![]() |
cb2340539d | ||
![]() |
17430210a1 | ||
![]() |
1655d85a53 | ||
![]() |
1df664d109 | ||
![]() |
a2e92b9d74 | ||
![]() |
1cdd6d21c5 | ||
![]() |
6fd64f9408 | ||
![]() |
69f5be3e31 | ||
![]() |
a9ebe9606e | ||
![]() |
d1f9f456bb | ||
![]() |
9e81c82452 | ||
![]() |
b3126934b3 | ||
![]() |
37bd4a7d0e | ||
![]() |
ae8a048ea6 | ||
![]() |
b0465e65c3 | ||
![]() |
036f11acaa | ||
![]() |
572e40ca27 |
@@ -1,3 +1,4 @@
|
||||
**/__pycache__
|
||||
/src-ui/.vscode
|
||||
/src-ui/node_modules
|
||||
/src-ui/dist
|
||||
@@ -10,3 +11,9 @@
|
||||
.pytest_cache
|
||||
/dist
|
||||
/scripts
|
||||
/resources
|
||||
**/tests
|
||||
**/*.spec.ts
|
||||
**/htmlcov
|
||||
/src/.pytest_cache
|
||||
.idea
|
||||
|
48
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Something is not working
|
||||
title: "[BUG] Concise description of the issue"
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!---
|
||||
=> Before opening an issue, please check the documentation and see if it helps you resolve your issue: https://paperless-ng.readthedocs.io/en/latest/troubleshooting.html
|
||||
=> Please also make sure that you followed the installation instructions.
|
||||
=> Please search the issues and look for similar issues before opening a bug report.
|
||||
|
||||
=> If you would like to submit a feature request please submit one under https://github.com/jonaswinkler/paperless-ng/discussions/categories/feature-requests
|
||||
|
||||
=> If you encounter issues while installing of configuring Paperless-ng, please post that in the "Support" section of the discussions. Remember that Paperless successfully runs on a variety of different systems. If paperless does not start, it's probably an issue with your system, and not an issue of paperless.
|
||||
|
||||
=> Don't remove the [BUG] prefix from the title.
|
||||
-->
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Webserver logs**
|
||||
```
|
||||
If available, post any logs from the web server related to your issue.
|
||||
```
|
||||
|
||||
**Relevant information**
|
||||
- Host OS of the machine running paperless: [e.g. Archlinux / Ubuntu 20.04]
|
||||
- Browser [e.g. chrome, safari]
|
||||
- Version [e.g. 1.0.0]
|
||||
- Installation method: [docker / bare metal]
|
||||
- Any configuration changes you made in `docker-compose.yml`, `docker-compose.env` or `paperless.conf`.
|
20
.github/ISSUE_TEMPLATE/other.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Other
|
||||
about: Anything that is not a feature request or bug.
|
||||
title: "[Other] Title of your issue"
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
|
||||
=> Discussions, Feedback and other suggestions belong in the "Discussion" section and not on the issue tracker.
|
||||
|
||||
=> If you would like to submit a feature request please submit one under https://github.com/jonaswinkler/paperless-ng/discussions/categories/feature-requests
|
||||
|
||||
=> If you encounter issues while installing of configuring Paperless-ng, please post that in the "Support" section of the discussions. Remember that Paperless successfully runs on a variety of different systems. If paperless does not start, it's probably is an issue with your system, and not an issue of paperless.
|
||||
|
||||
=> Don't remove the [Other] prefix from the title.
|
||||
|
||||
-->
|
77
.github/workflows/ansible.yml
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
---
|
||||
name: Ansible Role
|
||||
|
||||
on:
|
||||
push:
|
||||
branches-ignore:
|
||||
- 'translations**'
|
||||
pull_request:
|
||||
branches-ignore:
|
||||
- 'translations**'
|
||||
|
||||
jobs:
|
||||
# https://molecule.readthedocs.io/en/latest/ci.html#github-actions
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out the codebase
|
||||
uses: actions/checkout@v2
|
||||
if: github.event_name != 'pull_request'
|
||||
with:
|
||||
path: "${{ github.repository }}"
|
||||
- name: Check out the codebase
|
||||
uses: actions/checkout@v2
|
||||
if: github.event_name == 'pull_request'
|
||||
with:
|
||||
# merge commit is not available from tree at this point in time
|
||||
# https://github.com/actions/checkout#checkout-pull-request-head-commit-instead-of-merge-commit
|
||||
ref: "${{ github.event.pull_request.head.sha }}"
|
||||
path: "${{ github.repository }}"
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
- name: Set up Docker
|
||||
uses: docker-practice/actions-setup-docker@master
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python3 -m pip install --upgrade pip
|
||||
python3 -m pip install molecule[ansible,docker] jmespath
|
||||
ansible --version
|
||||
docker --version
|
||||
molecule --version
|
||||
python --version
|
||||
- name: Test installation/build/upgrade with molecule
|
||||
run: |
|
||||
cd ansible
|
||||
molecule create
|
||||
molecule verify
|
||||
molecule converge
|
||||
molecule idempotence
|
||||
molecule verify
|
||||
molecule destroy
|
||||
working-directory: "${{ github.repository }}"
|
||||
# # https://galaxy.ansible.com/docs/contributing/importing.html
|
||||
# release:
|
||||
# runs-on: ubuntu-latest
|
||||
# needs:
|
||||
# - test
|
||||
# # https://docs.github.com/en/free-pro-team@latest/actions/reference/context-and-expression-syntax-for-github-actions#github-context
|
||||
# if: contains(github.ref, 'refs/tags/')
|
||||
# steps:
|
||||
# - name: Check out the codebase
|
||||
# uses: actions/checkout@v2
|
||||
# with:
|
||||
# path: "${{ github.repository }}"
|
||||
# - name: Set up Python
|
||||
# uses: actions/setup-python@v2
|
||||
# - name: Install dependencies
|
||||
# run: |
|
||||
# python3 -m pip install --upgrade ansible-base
|
||||
# ansible --version
|
||||
# python --version
|
||||
# - name: Trigger a new import on Galaxy
|
||||
# # TODO Check if source if pulled from cwd or imported from github
|
||||
# # https://github.com/ansible/ansible/blob/devel/lib/ansible/cli/galaxy.py
|
||||
# run: |
|
||||
# cd ansible
|
||||
# ansible-galaxy role import --api-key ${{ secrets.GALAXY_API_KEY }} $(echo ${{ github.repository }} | cut -d/ -f1) $(echo ${{ github.repository }} | cut -d/ -f2)
|
||||
# working-directory: "${{ github.repository }}"
|
304
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,304 @@
|
||||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: ng-*
|
||||
branches-ignore:
|
||||
- 'translations**'
|
||||
pull_request:
|
||||
branches-ignore:
|
||||
- 'translations**'
|
||||
|
||||
jobs:
|
||||
documentation:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.8
|
||||
-
|
||||
name: Get pip cache dir
|
||||
id: pip-cache
|
||||
run: |
|
||||
echo "::set-output name=dir::$(pip cache dir)"
|
||||
-
|
||||
name: Persistent Github pip cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.pip-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-pip3.8}
|
||||
-
|
||||
name: Install dependencies
|
||||
run: |
|
||||
pip install --upgrade pipenv
|
||||
pipenv install --system --dev --ignore-pipfile
|
||||
-
|
||||
name: Make documentation
|
||||
run: |
|
||||
cd docs/
|
||||
make html
|
||||
-
|
||||
name: Upload artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: documentation
|
||||
path: docs/_build/html/
|
||||
|
||||
tests:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ['3.6', '3.7', '3.8', '3.9']
|
||||
fail-fast: false
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: "${{ matrix.python-version }}"
|
||||
-
|
||||
name: Get pip cache dir
|
||||
id: pip-cache
|
||||
run: |
|
||||
echo "::set-output name=dir::$(pip cache dir)"
|
||||
-
|
||||
name: Persistent Github pip cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.pip-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-pip${{ matrix.python-version }}
|
||||
-
|
||||
name: Prepare tests
|
||||
run: |
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -qq --no-install-recommends unpaper tesseract-ocr imagemagick ghostscript optipng
|
||||
pip install --upgrade pipenv
|
||||
pipenv install --system --dev --ignore-pipfile
|
||||
-
|
||||
name: Tests
|
||||
run: |
|
||||
cd src/
|
||||
pytest
|
||||
-
|
||||
name: Codestyle
|
||||
run: |
|
||||
cd src/
|
||||
pycodestyle
|
||||
-
|
||||
name: Publish coverage results
|
||||
if: matrix.python-version == '3.8'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
# https://github.com/coveralls-clients/coveralls-python/issues/251
|
||||
run: |
|
||||
cd src/
|
||||
coveralls --service=github
|
||||
|
||||
frontend:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '15'
|
||||
-
|
||||
name: Configure version on dev branches
|
||||
if: startsWith(github.ref, 'refs/heads/feature-') || github.ref == 'refs/heads/dev'
|
||||
run: |
|
||||
git_hash=$(git rev-parse --short "$GITHUB_SHA")
|
||||
git_branch=${GITHUB_REF#refs/heads/}
|
||||
sed -i -E "s/version: \"(.*)\"/version: \"${git_branch} ${git_hash}\"/g" src-ui/src/environments/environment.prod.ts
|
||||
-
|
||||
name: Build frontend
|
||||
run: ./compile-frontend.sh
|
||||
-
|
||||
name: Upload artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: frontend-compiled
|
||||
path: src/documents/static/frontend/
|
||||
|
||||
build-release:
|
||||
needs: [frontend, documentation, tests]
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.7
|
||||
-
|
||||
name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -qq --no-install-recommends gettext liblept5
|
||||
pip3 install -r requirements.txt
|
||||
-
|
||||
name: Download frontend artifact
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: frontend-compiled
|
||||
path: src/documents/static/frontend/
|
||||
-
|
||||
name: Download documentation artifact
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: documentation
|
||||
path: docs/_build/html/
|
||||
-
|
||||
name: Move files
|
||||
run: |
|
||||
mkdir dist
|
||||
mkdir dist/paperless-ng
|
||||
mkdir dist/paperless-ng/scripts
|
||||
cp .dockerignore .env Dockerfile Pipfile Pipfile.lock LICENSE README.md requirements.txt dist/paperless-ng/
|
||||
cp paperless.conf.example dist/paperless-ng/paperless.conf
|
||||
cp gunicorn.conf.py dist/paperless-ng/gunicorn.conf.py
|
||||
cp docker/ dist/paperless-ng/docker -r
|
||||
cp scripts/*.service scripts/*.sh dist/paperless-ng/scripts/
|
||||
cp src/ dist/paperless-ng/src -r
|
||||
cp docs/_build/html/ dist/paperless-ng/docs -r
|
||||
-
|
||||
name: Compile messages
|
||||
run: |
|
||||
cd dist/paperless-ng/src
|
||||
python3 manage.py compilemessages
|
||||
-
|
||||
name: Collect static files
|
||||
run: |
|
||||
cd dist/paperless-ng/src
|
||||
python3 manage.py collectstatic --no-input
|
||||
-
|
||||
name: Make release package
|
||||
run: |
|
||||
cd dist
|
||||
find . -name __pycache__ | xargs rm -r
|
||||
tar -cJf paperless-ng.tar.xz paperless-ng/
|
||||
-
|
||||
name: Upload release artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: release
|
||||
path: dist/paperless-ng.tar.xz
|
||||
|
||||
publish-release:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-release
|
||||
if: contains(github.ref, 'refs/tags/ng-')
|
||||
steps:
|
||||
-
|
||||
name: Download release artifact
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: release
|
||||
path: ./
|
||||
-
|
||||
name: Get version
|
||||
id: get_version
|
||||
run: |
|
||||
echo ::set-output name=version::${GITHUB_REF#refs/tags/ng-}
|
||||
-
|
||||
name: Create release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ng-${{ steps.get_version.outputs.version }}
|
||||
release_name: Paperless-ng ${{ steps.get_version.outputs.version }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
body: |
|
||||
For a complete list of changes, see the changelog at https://paperless-ng.readthedocs.io/en/latest/changelog.html.
|
||||
-
|
||||
name: Upload release archive
|
||||
id: upload-release-asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
|
||||
asset_path: ./paperless-ng.tar.xz
|
||||
asset_name: paperless-ng-${{ steps.get_version.outputs.version }}.tar.xz
|
||||
asset_content_type: application/x-xz
|
||||
|
||||
# build and push image to docker hub.
|
||||
build-docker-image:
|
||||
if: github.event_name == 'push' && (startsWith(github.ref, 'refs/heads/feature-') || github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/ng-'))
|
||||
runs-on: ubuntu-latest
|
||||
needs: [frontend, tests]
|
||||
steps:
|
||||
-
|
||||
name: Prepare
|
||||
id: prepare
|
||||
run: |
|
||||
IMAGE_NAME=jonaswinkler/paperless-ng
|
||||
if [[ $GITHUB_REF == refs/tags/ng-* ]]; then
|
||||
TAGS=${IMAGE_NAME}:${GITHUB_REF#refs/tags/ng-},${IMAGE_NAME}:latest
|
||||
INSPECT_TAG=${IMAGE_NAME}:latest
|
||||
elif [[ $GITHUB_REF == refs/heads/* ]]; then
|
||||
TAGS=${IMAGE_NAME}:${GITHUB_REF#refs/heads/}
|
||||
INSPECT_TAG=${TAGS}
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
echo ::set-output name=tags::${TAGS}
|
||||
echo ::set-output name=inspect_tag::${INSPECT_TAG}
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Download frontend artifact
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: frontend-compiled
|
||||
path: src/documents/static/frontend/
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
-
|
||||
name: Cache Docker layers
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: /tmp/.buildx-cache
|
||||
key: ${{ runner.os }}-buildx-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-buildx-
|
||||
-
|
||||
name: Login to DockerHub
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
-
|
||||
name: Build and push
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
platforms: linux/amd64,linux/arm/v7,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.prepare.outputs.tags }}
|
||||
cache-from: type=local,src=/tmp/.buildx-cache
|
||||
cache-to: type=local,dest=/tmp/.buildx-cache
|
||||
-
|
||||
name: Inspect image
|
||||
run: |
|
||||
docker buildx imagetools inspect ${{ steps.prepare.outputs.inspect_tag }}
|
18
.gitignore
vendored
@@ -65,8 +65,8 @@ target/
|
||||
.virtualenv
|
||||
virtualenv
|
||||
/venv
|
||||
docker-compose.env
|
||||
docker-compose.yml
|
||||
/docker-compose.env
|
||||
/docker-compose.yml
|
||||
|
||||
# Used for development
|
||||
scripts/import-for-development
|
||||
@@ -76,17 +76,13 @@ scripts/nuke
|
||||
/static/
|
||||
|
||||
# Stored PDFs
|
||||
/media/documents/originals/*
|
||||
/media/documents/thumbnails/*
|
||||
|
||||
/data/classification_model.pickle
|
||||
/data/db.sqlite3
|
||||
/data/index
|
||||
|
||||
/media/
|
||||
/data/
|
||||
/paperless.conf
|
||||
/consume
|
||||
/export
|
||||
/consume/
|
||||
/export/
|
||||
/src-ui/.vscode
|
||||
|
||||
# this is where the compiled frontend is moved to.
|
||||
/src/documents/static/frontend/
|
||||
/docs/.vscode/settings.json
|
||||
|
16
.readthedocs.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
# .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.7
|
||||
install:
|
||||
- requirements: docs/requirements.txt
|
22
.travis.yml
@@ -1,22 +0,0 @@
|
||||
language: python
|
||||
|
||||
python:
|
||||
- "3.6"
|
||||
- "3.7"
|
||||
- "3.8"
|
||||
|
||||
before_install:
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -qq libpoppler-cpp-dev unpaper tesseract-ocr
|
||||
|
||||
install:
|
||||
- pip install --upgrade pipenv
|
||||
- pipenv install --system --dev
|
||||
|
||||
script:
|
||||
- cd src/
|
||||
- pipenv run pytest --cov
|
||||
- pipenv run pycodestyle
|
||||
|
||||
after_success:
|
||||
- pipenv run coveralls
|
@@ -1,13 +1,30 @@
|
||||
# Contributing
|
||||
|
||||
If you feel that somethings is not working, please submit an issue. You can also ask questions on the issue tracker by tagging your question with the question tag.
|
||||
There's still lots of things to be done, just have a look at that issue log. If you feel like conctributing to the project, please do! Bug fixes and improvements to the front end (I just can't seem to get some of these CSS things right) are always welcome.
|
||||
|
||||
Pull requests are welcome, however, I will be a little bit more strict about what goes into the code and what does not. If you want to make a big change, please ask me about it first.
|
||||
If you want to implement something big: Please start a discussion about that in the issues! Maybe I've already had something similar in mind and we can make it happen together. However, keep in mind that the general roadmap is to make the existing features stable and get them tested. See the roadmap in the readme.
|
||||
|
||||
* When making additions to the project, consider if the majority of users will benefit from your change. If not, you're probably better of forking the project.
|
||||
* Also consider if your change will get in the way of other users. A good change is a change that enhances the experience of some users who want that change and does not affect users who do not care about the change.
|
||||
|
||||
However:
|
||||
## Python
|
||||
|
||||
* Bug fixes and are always welcome. Docker makes things easier, however, I alone cannot ensure that this runs on all platforms.
|
||||
* Improvements to the styling of the front-end are always welcome. I'm no expert in things UX, and simply copied one of the Bootstrap examples. I think it turned out rather good, but I just can't seem to get some things working properly.
|
||||
Use python 3.6 for development. Paperless supports python 3.6, 3.7 and 3.8.
|
||||
|
||||
## Branches
|
||||
|
||||
master always reflects the latest release.
|
||||
|
||||
dev contains all changes that will be part of the next release. Use this branch to start making your changes.
|
||||
|
||||
feature-X branches is for experimental stuff that will eventually be merged into dev, and then released as part of the next release.
|
||||
|
||||
## Testing:
|
||||
|
||||
I'm trying to get most of paperless tested, so please do the same for your code! I know its a hassle, but it makes sure that your code works now and will allow us to detect regressions easily.
|
||||
|
||||
To test your code, execute `pytest` in the src/ directory. Executing that in the project root is no good. This also generates a html coverage report, which you can use to see if you missed anything important during testing.
|
||||
|
||||
## More info:
|
||||
|
||||
... is available in the documentation. https://paperless-ng.readthedocs.io/en/latest/extending.html
|
||||
|
109
Dockerfile
Normal file
@@ -0,0 +1,109 @@
|
||||
FROM ubuntu:20.04 AS jbig2enc
|
||||
|
||||
WORKDIR /usr/src/jbig2enc
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends build-essential automake libtool libleptonica-dev zlib1g-dev git ca-certificates
|
||||
|
||||
RUN git clone https://github.com/agl/jbig2enc .
|
||||
RUN ./autogen.sh
|
||||
RUN ./configure && make
|
||||
|
||||
FROM python:3.7-slim
|
||||
|
||||
# Binary dependencies
|
||||
RUN apt-get update \
|
||||
&& apt-get -y --no-install-recommends install \
|
||||
# Basic dependencies
|
||||
curl \
|
||||
file \
|
||||
# fonts for text file thumbnail generation
|
||||
fonts-liberation \
|
||||
# for making translations further down
|
||||
gettext \
|
||||
gnupg \
|
||||
imagemagick \
|
||||
# for Numpy
|
||||
libatlas-base-dev \
|
||||
libxslt1-dev \
|
||||
mime-support \
|
||||
# thumbnail size reduction
|
||||
optipng \
|
||||
sudo \
|
||||
tzdata \
|
||||
# OCRmyPDF dependencies
|
||||
ghostscript \
|
||||
icc-profiles-free \
|
||||
liblept5 \
|
||||
libxml2 \
|
||||
pngquant \
|
||||
qpdf \
|
||||
tesseract-ocr \
|
||||
tesseract-ocr-eng \
|
||||
tesseract-ocr-deu \
|
||||
tesseract-ocr-fra \
|
||||
tesseract-ocr-ita \
|
||||
tesseract-ocr-spa \
|
||||
unpaper \
|
||||
zlib1g \
|
||||
|
||||
# This pulls in updated dependencies from bullseye to fix some issues with file type detection.
|
||||
# TODO: Remove this once bullseye releases.
|
||||
&& echo "deb http://deb.debian.org/debian bullseye main" > /etc/apt/sources.list.d/bullseye.list \
|
||||
&& apt-get update \
|
||||
&& apt-get install --no-install-recommends -y file libmagic-dev \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& rm /etc/apt/sources.list.d/bullseye.list
|
||||
|
||||
# copy jbig2enc
|
||||
COPY --from=jbig2enc /usr/src/jbig2enc/src/.libs/libjbig2enc* /usr/local/lib/
|
||||
COPY --from=jbig2enc /usr/src/jbig2enc/src/jbig2 /usr/local/bin/
|
||||
COPY --from=jbig2enc /usr/src/jbig2enc/src/*.h /usr/local/include/
|
||||
|
||||
WORKDIR /usr/src/paperless/src/
|
||||
|
||||
COPY requirements.txt ../
|
||||
|
||||
# Python dependencies
|
||||
RUN apt-get update \
|
||||
&& apt-get -y --no-install-recommends install \
|
||||
build-essential \
|
||||
libpq-dev \
|
||||
libqpdf-dev \
|
||||
&& python3 -m pip install --upgrade --no-cache-dir supervisor \
|
||||
&& python3 -m pip install --no-cache-dir -r ../requirements.txt \
|
||||
&& apt-get -y purge build-essential libqpdf-dev \
|
||||
&& apt-get -y autoremove --purge \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# setup docker-specific things
|
||||
COPY docker/ ./docker/
|
||||
|
||||
RUN cd docker \
|
||||
&& cp imagemagick-policy.xml /etc/ImageMagick-6/policy.xml \
|
||||
&& mkdir /var/log/supervisord /var/run/supervisord \
|
||||
&& cp supervisord.conf /etc/supervisord.conf \
|
||||
&& cp docker-entrypoint.sh /sbin/docker-entrypoint.sh \
|
||||
&& chmod 755 /sbin/docker-entrypoint.sh \
|
||||
&& chmod +x install_management_commands.sh \
|
||||
&& ./install_management_commands.sh \
|
||||
&& cd .. \
|
||||
&& rm docker -rf
|
||||
|
||||
COPY gunicorn.conf.py ../
|
||||
|
||||
# copy app
|
||||
COPY src/ ./
|
||||
|
||||
# add users, setup scripts
|
||||
RUN addgroup --gid 1000 paperless \
|
||||
&& useradd --uid 1000 --gid paperless --home-dir /usr/src/paperless paperless \
|
||||
&& chown -R paperless:paperless ../ \
|
||||
&& sudo -HEu paperless python3 manage.py collectstatic --clear --no-input \
|
||||
&& sudo -HEu paperless python3 manage.py compilemessages
|
||||
|
||||
VOLUME ["/usr/src/paperless/data", "/usr/src/paperless/media", "/usr/src/paperless/consume", "/usr/src/paperless/export"]
|
||||
ENTRYPOINT ["/sbin/docker-entrypoint.sh"]
|
||||
EXPOSE 8000
|
||||
CMD ["/usr/local/bin/supervisord", "-c", "/etc/supervisord.conf"]
|
||||
|
||||
LABEL maintainer="Jonas Winkler <dev@jpwinkler.de>"
|
66
Pipfile
@@ -9,43 +9,63 @@ verify_ssl = true
|
||||
name = "piwheels"
|
||||
|
||||
[packages]
|
||||
django = "~=3.1"
|
||||
pillow = "*"
|
||||
dateparser = "~=0.7"
|
||||
dateparser = "~=0.7.6"
|
||||
django = "~=3.1.3"
|
||||
django-cors-headers = "*"
|
||||
djangorestframework = "~=3.12"
|
||||
django-extensions = "*"
|
||||
django-filter = "~=2.4.0"
|
||||
django-q = "~=1.3.4"
|
||||
djangorestframework = "~=3.12.2"
|
||||
filelock = "*"
|
||||
fuzzywuzzy = {extras = ["speedup"], version = "*"}
|
||||
gunicorn = "*"
|
||||
imap-tools = "*"
|
||||
langdetect = "*"
|
||||
# numpy 1.20.0 drops python 3.6 support
|
||||
numpy = "~=1.19.5"
|
||||
pathvalidate = "*"
|
||||
# pinned to 8.1.0, since aarch64 wheels might not be available beyond that https://github.com/python-pillow/Pillow/issues/5202
|
||||
pillow = "==8.1.0"
|
||||
pikepdf = "~=2.5.0"
|
||||
python-gnupg = "*"
|
||||
python-dotenv = "*"
|
||||
filemagic = "*"
|
||||
pyocr = "~=0.7"
|
||||
langdetect = "*"
|
||||
pdftotext = "*"
|
||||
django-filter = "~=2.4"
|
||||
python-dateutil = "*"
|
||||
python-magic = "*"
|
||||
psycopg2-binary = "*"
|
||||
scikit-learn="~=0.23"
|
||||
whoosh="~=2.7"
|
||||
gunicorn = "*"
|
||||
whitenoise = "~=5.2"
|
||||
fuzzywuzzy = "*"
|
||||
python-Levenshtein = "*"
|
||||
django-extensions = "*"
|
||||
watchdog = "*"
|
||||
pathvalidate = "*"
|
||||
django-q = "*"
|
||||
redis = "*"
|
||||
imap-tools = "*"
|
||||
# Pinned because aarch64 wheels and updates cause warnings when loading the classifier model.
|
||||
scikit-learn="==0.24.0"
|
||||
# Prevent scipy updates because 1.6 is incompatible with python 3.6
|
||||
scipy="~=1.5.4"
|
||||
whitenoise = "~=5.2.0"
|
||||
watchdog = "~=1.0.0"
|
||||
whoosh="~=2.7.4"
|
||||
inotifyrecursive = "~=0.3.4"
|
||||
ocrmypdf = "~=11.6"
|
||||
tqdm = "*"
|
||||
tika = "*"
|
||||
# TODO: This will sadly also install daphne+dependencies,
|
||||
# which an ASGI server we don't need. Adds about 15MB image size.
|
||||
channels = "~=3.0"
|
||||
channels-redis = "*"
|
||||
uvicorn = {extras = ["standard"], version = "*"}
|
||||
concurrent-log-handler = "*"
|
||||
# uvloop 0.15+ incompatible with python 3.6
|
||||
uvloop = "~=0.14.0"
|
||||
# TODO: keep an eye on piwheel builds and update this once available (https://www.piwheels.org/project/cryptography/)
|
||||
cryptography = "~=3.3.2"
|
||||
"pdfminer.six" = "*"
|
||||
|
||||
[dev-packages]
|
||||
coveralls = "*"
|
||||
factory-boy = "*"
|
||||
sphinx = "~=3.3"
|
||||
tox = "*"
|
||||
pycodestyle = "*"
|
||||
pytest = "*"
|
||||
pytest-cov = "*"
|
||||
pytest-django = "*"
|
||||
pytest-sugar = "*"
|
||||
pytest-env = "*"
|
||||
pytest-sugar = "*"
|
||||
pytest-xdist = "*"
|
||||
sphinx = "~=3.4.2"
|
||||
sphinx_rtd_theme = "*"
|
||||
tox = "*"
|
||||
|
1328
Pipfile.lock
generated
116
README.md
@@ -1,90 +1,112 @@
|
||||
[](https://travis-ci.org/jonaswinkler/paperless-ng)
|
||||
[](https://github.com/jonaswinkler/paperless-ng/actions)
|
||||

|
||||
[](https://paperless-ng.readthedocs.io/en/latest/?badge=latest)
|
||||
[](https://gitter.im/paperless-ng/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://hub.docker.com/r/jonaswinkler/paperless-ng)
|
||||
[](https://coveralls.io/github/jonaswinkler/paperless-ng?branch=master)
|
||||
|
||||
# Paperless-ng
|
||||
|
||||
[Paperless](https://github.com/the-paperless-project/paperless) is an application by Daniel Quinn and others that indexes your scanned documents and allows you to easily search for documents and store metadata alongside your documents.
|
||||
[Paperless (click me)](https://github.com/the-paperless-project/paperless) is an application by Daniel Quinn and contributors that indexes your scanned documents and allows you to easily search for documents and store metadata alongside your documents.
|
||||
|
||||
Paperless-ng is a fork of the original project, adding a new interface and many other changes under the hood. For a detailed list of changes, see below.
|
||||
Paperless-ng is a fork of the original project, adding a new interface and many other changes under the hood. These key points should help you decide whether Paperless-ng is something you would prefer over Paperless:
|
||||
|
||||
This project is still in development and some things may not work as expected.
|
||||
* Interface: The new front end is the main interface for paperless-ng, the old interface still exists but most customizations (such as thumbnails for the document list) have been removed.
|
||||
* Encryption: Paperless-ng does not support GnuPG anymore, since storing your data on encrypted file systems (that you optionally mount on demand) achieves about the same result.
|
||||
* Resource usage: Paperless-ng does use a bit more resources than Paperless. Running the web server requires about 300MB of RAM or more, depending on the configuration. While adding documents, it requires about 300MB additional RAM, depending on the document. It still runs on Pi (many users do that), but it has been generally geared to better use the resources of more powerful systems.
|
||||
* API changes: If you rely on the REST API of paperless, some of its functionality has been changed.
|
||||
|
||||
For a detailed list of changes, have a look at the [change log](https://paperless-ng.readthedocs.io/en/latest/changelog.html) in the documentation.
|
||||
|
||||
# How it Works
|
||||
|
||||
Paperless does not control your scanner, it only helps you deal with what your scanner produces.
|
||||
|
||||
1. Buy a document scanner that can write to a place on your network. If you need some inspiration, have a look at the [scanner recommendations](https://paperless.readthedocs.io/en/latest/scanners.html) page.
|
||||
2. Set it up to "scan to FTP" or something similar. It should be able to push scanned images to a server without you having to do anything. Of course if your scanner doesn't know how to automatically upload the file somewhere, you can always do that manually. Paperless doesn't care how the documents get into its local consumption directory.
|
||||
3. Have the target server run the Paperless consumption script to OCR the file and index it into a local database.
|
||||
4. Use the web frontend to sift through the database and find what you want.
|
||||
5. Download the PDF you need/want via the web interface and do whatever you like with it. You can even print it and send it as if it's the original. In most cases, no one will care or notice.
|
||||
1. Buy a document scanner that can write to a place on your network. If you need some inspiration, have a look at the [scanner recommendations](https://paperless-ng.readthedocs.io/en/latest/scanners.html) page. Set it up to "scan to FTP" or something similar. It should be able to push scanned images to a server without you having to do anything. Of course if your scanner doesn't know how to automatically upload the file somewhere, you can always do that manually. Paperless doesn't care how the documents get into its local consumption directory.
|
||||
|
||||
- Alternatively, you can use any of the mobile scanning apps out there. We have an app that allows you to share documents with paperless, if you're on Android. See the section on affiliated projects.
|
||||
|
||||
2. Wait for paperless to process your files. OCR is expensive, and depending on the power of your machine, this might take a bit of time.
|
||||
3. Use the web frontend to sift through the database and find what you want.
|
||||
4. Download the PDF you need/want via the web interface and do whatever you like with it. You can even print it and send it as if it's the original. In most cases, no one will care or notice.
|
||||
|
||||
Here's what you get:
|
||||
|
||||

|
||||

|
||||
|
||||
# Why Paperless-ng?
|
||||
# Features
|
||||
|
||||
I wanted to make big changes to the project that will impact the way it is used by its users greatly. Among the users who currently use paperless in production there are probably many that don't want these changes right away. I also wanted to have more control over what goes into the code and what does not. Therefore, paperless-ng was created. 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-ng.
|
||||
|
||||
The gist of the changes is the following:
|
||||
|
||||
* New front end. This will eventually be mobile friendly as well.
|
||||
* New full text search.
|
||||
* 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-ng.readthedocs.io/en/latest/configuration.html#tika-settings))
|
||||
* 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.
|
||||
* Filtering by tags, correspondents, types, and more.
|
||||
* Customizable views can be saved and displayed on the dashboard.
|
||||
* Full text search helps you find what you need.
|
||||
* Auto completion suggests relevant words from your documents.
|
||||
* Results are sorted by relevance to your search query.
|
||||
* Highlighting shows you which parts of the document matched the query.
|
||||
* Searching for similar documents ("More like this")
|
||||
* Email processing: Paperless adds documents from your email accounts.
|
||||
* Configure multiple accounts and filters for each account.
|
||||
* When adding documents from mails, paperless can move these mails to a new folder, mark them as read, flag them as important or delete them.
|
||||
* Machine learning powered document matching.
|
||||
* Code cleanup in many, MANY areas.
|
||||
* Paperless 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-ng consumes multiple documents in parallel.
|
||||
* The integrated sanity checker makes sure that your document archive is in good health.
|
||||
|
||||
If you want to see some screenshots of paperless-ng in action, [some are available in the documentation](https://paperless-ng.readthedocs.io/en/latest/screenshots.html).
|
||||
|
||||
For a complete list of changes, check out the [changelog](https://paperless-ng.readthedocs.io/en/latest/changelog.html)
|
||||
|
||||
## Planned
|
||||
|
||||
These features will make it into the application at some point, sorted by priority.
|
||||
|
||||
- **More search.** The search backend is incredibly versatile and customizable. Searching is the most important feature of this project and thus, I want to implement things like:
|
||||
- Group and limit search results by correspondent, show “more from this” links in the results.
|
||||
- Ability to search for “Similar documents” in the search results
|
||||
- Provide corrections for mispelled queries
|
||||
- **More robust consumer** that shows its progress on the web page.
|
||||
- **More rigid email processing**. Like, dont delete imported mail, provide filters, etc...
|
||||
- **Arbitrary tag colors**. Allow the selection of any color with a color picker.
|
||||
|
||||
## On the chopping block.
|
||||
|
||||
I don't know if these features are used all that much. I don't exactly know how they work and will probably remove them at some point in the future.
|
||||
|
||||
- **GnuPG encrypion.** Since its disabled by default and the website allows transparent access to encrypted documents anyway, this doesn’t really provide any benefit over having the application stored on an encrypted file system.
|
||||
|
||||
# Getting started
|
||||
|
||||
The recommended way to deploy paperless is docker-compose. Use the provided docker-compose.yml files to get started. This pulls the image from Docker hub. Alternatively, you can build the image yourself.
|
||||
The recommended way to deploy paperless is docker-compose. The files in the /docker/hub directory are configured to pull the image from Docker Hub.
|
||||
|
||||
Read the [documentation](https://paperless-ng.readthedocs.io/en/latest/setup.html#installation) on how to get started.
|
||||
|
||||
Alternatively, you can install the dependencies and setup apache and a database server yourself. Details for that will be available in the documentation.
|
||||
Alternatively, you can install the dependencies and setup apache and a database server yourself. The documenation has a step by step guide on how to do it.
|
||||
|
||||
# Migrating to paperless-ng
|
||||
|
||||
Read the section about [migration](https://paperless-ng.readthedocs.io/en/latest/setup.html#migration-to-paperless-ng) in the documentation.
|
||||
Read the section about [migration](https://paperless-ng.readthedocs.io/en/latest/setup.html#migration-to-paperless-ng) in the documentation. Its also entirely possible to go back to paperless by reverting the database migrations.
|
||||
|
||||
# Documentation
|
||||
|
||||
The documentation for Paperless-ng is available on [ReadTheDocs](https://paperless-ng.readthedocs.io/).
|
||||
|
||||
# Translation
|
||||
|
||||
Paperless is currently available in English, German, Dutch and French. Translation is coordinated at transifex: https://www.transifex.com/paperless/paperless-ng
|
||||
|
||||
If you want to see paperless in your own language, request that language at transifex and you can start translating after I approve the language.
|
||||
|
||||
# Feature Requests
|
||||
|
||||
Feature requests can be submitted via [GitHub Discussions](https://github.com/jonaswinkler/paperless-ng/discussions/categories/feature-requests), you can search for existing ideas, add your own and vote for the ones you care about! Note that some older feature requests can also be found under [issues](https://github.com/jonaswinkler/paperless-ng/issues).
|
||||
|
||||
# Questions? Something not working?
|
||||
|
||||
For bugs please [open an issue](https://github.com/jonaswinkler/paperless-ng/issues) or [start a discussion](https://github.com/jonaswinkler/paperless-ng/discussions) if you have questions.
|
||||
|
||||
## Feel like helping out?
|
||||
|
||||
There's still lots of things to be done, just have a look at open issues & discussions. If you feel like contributing to the project, please do! Bug fixes and improvements to the front end (I just can't seem to get some of these CSS things right) are always welcome. The documentation has some basic information on how to get started.
|
||||
|
||||
If you want to implement something big: Please start a discussion about that in the issues! Maybe I've already had something similar in mind and we can make it happen together. However, keep in mind that the general roadmap is to make the existing features stable and get them tested. See the roadmap above.
|
||||
|
||||
# Affiliated Projects
|
||||
|
||||
Paperless has been around a while now, and people are starting to build stuff on top of it. If you're one of those people, we can add your project to this list:
|
||||
|
||||
* [Paperless App](https://github.com/bauerj/paperless_app): An Android/iOS app for Paperless.
|
||||
* [Paperless Desktop](https://github.com/thomasbrueggemann/paperless-desktop): A desktop UI for your Paperless installation. Runs on Mac, Linux, and Windows.
|
||||
* [ansible-role-paperless](https://github.com/ovv/ansible-role-paperless): An easy way to get Paperless running via Ansible.
|
||||
* [paperless-cli](https://github.com/stgarf/paperless-cli): A golang command line binary to interact with a Paperless instance.
|
||||
* [Paperless App](https://github.com/bauerj/paperless_app): An Android/iOS app for Paperless. Updated to work with 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.
|
||||
|
||||
Compatibility with Paperless-ng is unknown.
|
||||
These projects also exist, but their status and compatibility with paperless-ng is unknown.
|
||||
|
||||
* [Paperless Desktop](https://github.com/thomasbrueggemann/paperless-desktop): A desktop UI for your Paperless installation. Runs on Mac, Linux, and Windows.
|
||||
* [paperless-cli](https://github.com/stgarf/paperless-cli): A golang command line binary to interact with a Paperless instance.
|
||||
|
||||
# Important Note
|
||||
|
||||
Document scanners are typically used to scan sensitive documents. Things like your social insurance number, tax records, invoices, etc. Everything is stored in the clear without encryption by default (it needs to be searchable, so if someone has ideas on how to do that on encrypted data, I'm all ears). This means that Paperless should never be run on an untrusted host. Instead, I recommend that if you do want to use it, run it locally on a server in your own home.
|
||||
Document scanners are typically used to scan sensitive documents. Things like your social insurance number, tax records, invoices, etc. Everything is stored in the clear without encryption. This means that Paperless should never be run on an untrusted host. Instead, I recommend that if you do want to use it, run it locally on a server in your own home.
|
||||
|
114
ansible/README.md
Normal file
@@ -0,0 +1,114 @@
|
||||
Ansible Role: paperless-ng
|
||||
==========================
|
||||
|
||||
Installs and configures paperless-ng EDMS on Debian/Ubuntu systems.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
No special system requirements. Ansible 2.7 or newer is required.
|
||||
|
||||
Note that this role requires root access, so either run it in a playbook with a global `become: yes`, or invoke the role in your playbook like:
|
||||
|
||||
- hosts: all
|
||||
roles:
|
||||
- role: ansible
|
||||
become: yes
|
||||
|
||||
Role Variables
|
||||
--------------
|
||||
|
||||
Most configuration variables from paperless-ng itself are available and accept their respective arguments.
|
||||
Every `PAPERLESS_*` configuration varaible is lowercased and instead prefixed with `paperlessng_*` in `defaults/main.yml`.
|
||||
|
||||
For a full listing including explainations and allowed values, see the current [documentation](https://paperless-ng.readthedocs.io/en/ng-0.9.14/configuration.html).
|
||||
|
||||
Additional variables available in this role are listed below, along with default values:
|
||||
|
||||
paperlessng_version: 0.9.14
|
||||
|
||||
The [release](https://github.com/jonaswinkler/paperless-ng/releases) archive version of paperless-ng to install.
|
||||
|
||||
paperlessng_redis_host: localhost
|
||||
paperlessng_redis_port: 6379
|
||||
|
||||
Seperate configuration values that combine into `PAPERLESS_REDIS`.
|
||||
|
||||
paperlessng_db_type: sqlite
|
||||
|
||||
Database to use. Default is file-based SQLite.
|
||||
|
||||
paperlessng_db_host: localhost
|
||||
paperlessng_db_port: 5432
|
||||
paperlessng_db_name: paperlessng
|
||||
paperlessng_db_user: paperlessng
|
||||
paperlessng_db_pass: paperlessng
|
||||
paperlessng_db_sslmode: prefer
|
||||
|
||||
Database configuration (only applicable if `paperlessng_db_type == 'postgresql'`).
|
||||
|
||||
paperlessng_directory: /opt/paperless-ng
|
||||
|
||||
Root directory paperless-ng is installed into.
|
||||
|
||||
paperlessng_virtualenv: "{{ paperlessng_directory }}/.venv"
|
||||
|
||||
Directory used for the virtual environment for paperless-ng.
|
||||
|
||||
paperlessng_ocr_languages:
|
||||
- eng
|
||||
|
||||
List of OCR languages to install and configure (`apt search tesseract-ocr-*`).
|
||||
|
||||
paperlessng_use_jbig2enc: True
|
||||
|
||||
Whether to install and use [jbig2enc](https://github.com/agl/jbig2enc) for OCRmyPDF.
|
||||
|
||||
paperlessng_big2enc_lossy: False
|
||||
|
||||
Whether to use jbig2enc's lossy compression mode.
|
||||
|
||||
paperlessng_superuser_name: paperlessng
|
||||
paperlessng_superuser_email: paperlessng@example.com
|
||||
paperlessng_superuser_password: paperlessng
|
||||
|
||||
Credentials of the initial superuser in paperless-ng.
|
||||
|
||||
paperlessng_system_user: paperlessng
|
||||
paperlessng_system_group: paperlessng
|
||||
|
||||
System user and group to run the paperless-ng services as (will be created if required).
|
||||
|
||||
paperlessng_listen_address: 127.0.0.1
|
||||
paperlessng_listen_port: 8000
|
||||
|
||||
Address and port for the paperless-ng service to listen on.
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
No ansible dependencies.
|
||||
|
||||
Example Playbook
|
||||
----------------
|
||||
`playbook.yml`:
|
||||
|
||||
- hosts: all
|
||||
become: yes
|
||||
vars_files:
|
||||
- vars/main.yml
|
||||
roles:
|
||||
- ansible
|
||||
|
||||
`vars/main.yml`:
|
||||
|
||||
paperlessng_media_root: /mnt/media/smbshare
|
||||
|
||||
paperlessng_db_type: postgresql
|
||||
paperlessng_db_pass: PLEASEPROVIDEASTRONGPASSWORDHERE
|
||||
|
||||
paperlessng_secret_key: AGAINPLEASECHANGETHISNOW
|
||||
|
||||
paperlessng_ocr_languages:
|
||||
- eng
|
||||
- deu
|
78
ansible/defaults/main.yml
Normal file
@@ -0,0 +1,78 @@
|
||||
---
|
||||
paperlessng_version: latest # 'latest', release number, or github branch/tag/commit/ref
|
||||
|
||||
# Required services
|
||||
paperlessng_redis_host: localhost
|
||||
paperlessng_redis_port: 6379
|
||||
paperlessng_db_type: sqlite # or postgresql
|
||||
# Below entries only apply for paperlessng_db_type=='postgresql'
|
||||
paperlessng_db_host: localhost
|
||||
paperlessng_db_port: 5432
|
||||
paperlessng_db_name: paperlessng
|
||||
paperlessng_db_user: paperlessng
|
||||
paperlessng_db_pass: paperlessng
|
||||
paperlessng_db_sslmode: prefer
|
||||
|
||||
# Paths and folders
|
||||
paperlessng_directory: /opt/paperless-ng
|
||||
paperlessng_consumption_dir: "{{ paperlessng_directory }}/consumption"
|
||||
paperlessng_data_dir: "{{ paperlessng_directory }}/data"
|
||||
paperlessng_media_root: "{{ paperlessng_directory }}/media"
|
||||
paperlessng_static_dir: "{{ paperlessng_directory }}/static"
|
||||
paperlessng_filename_format:
|
||||
paperlessng_virtualenv: "{{ paperlessng_directory }}/.venv"
|
||||
|
||||
# Hosting & Security
|
||||
paperlessng_secret_key: PLEASECHANGETHISFORTHELOVEOFGOD
|
||||
paperlessng_allowed_hosts: "*"
|
||||
paperlessng_cors_allowed_hosts: http://localhost:8000
|
||||
paperlessng_force_script_name:
|
||||
paperlessng_static_url: /static/
|
||||
paperlessng_auto_login_username:
|
||||
paperlessng_cookie_prefix: ""
|
||||
paperlessng_enable_http_remote_user: False
|
||||
|
||||
# OCR settings
|
||||
paperlessng_ocr_languages:
|
||||
- eng
|
||||
paperlessng_ocr_mode: skip
|
||||
paperlessng_ocr_output_type: pdfa
|
||||
paperlessng_ocr_pages: 0
|
||||
paperlessng_ocr_image_dpi:
|
||||
# see https://ocrmypdf.readthedocs.io/en/latest/api.html#ocrmypdf.ocr
|
||||
paperlessng_ocr_user_args:
|
||||
#- "deskew": True # https://github.com/jonaswinkler/paperless-ng/issues/231
|
||||
- "optimize": 1
|
||||
paperlessng_use_jbig2enc: True
|
||||
paperlessng_big2enc_lossy: False
|
||||
|
||||
# Tika settings
|
||||
paperlessng_tika_enabled: False
|
||||
paperlessng_tika_endpoint: http://localhost:9998
|
||||
paperlessng_tika_gotenberg_endpoint: http://localhost:3000
|
||||
|
||||
# Software tweaks
|
||||
paperlessng_time_zone: Europe/Berlin
|
||||
paperlessng_consumer_polling: 0
|
||||
paperlessng_consumer_delete_duplicates: False
|
||||
paperlessng_consumer_recursive: False
|
||||
paperlessng_consumer_subdirs_as_tags: False
|
||||
paperlessng_optimize_thumbnails: True
|
||||
paperlessng_post_consume_script:
|
||||
paperlessng_filename_date_order:
|
||||
paperlessng_filename_parse_transforms:
|
||||
paperlessng_thumbnail_font_name: /usr/share/fonts/liberation/LiberationSerif-Regular.ttf
|
||||
paperlessng_ignore_dates: ""
|
||||
|
||||
# Superuser settings
|
||||
paperlessng_superuser_name: paperlessng
|
||||
paperlessng_superuser_email: paperlessng@example.com
|
||||
paperlessng_superuser_password: paperlessng
|
||||
|
||||
# System user settings
|
||||
paperlessng_system_user: paperlessng
|
||||
paperlessng_system_group: paperlessng
|
||||
|
||||
# Webserver settings
|
||||
paperlessng_listen_address: 127.0.0.1
|
||||
paperlessng_listen_port: 8000
|
17
ansible/meta/main.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
dependencies: []
|
||||
|
||||
galaxy_info:
|
||||
author: C0nsultant
|
||||
description: Bare-metal deployment of paperless-ng DMS
|
||||
license: license (GPLv3)
|
||||
min_ansible_version: 2.7
|
||||
|
||||
platforms:
|
||||
- name: Debian
|
||||
versions:
|
||||
- buster
|
||||
- name: Ubuntu
|
||||
versions:
|
||||
- focal
|
||||
|
||||
galaxy_tags: [EDMS, django, python, web]
|
10
ansible/molecule/default/converge.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
- name: update previous release to newest release
|
||||
hosts: all
|
||||
tasks:
|
||||
- name: set current github commit as version when available
|
||||
set_fact:
|
||||
paperlessng_version: "{{ lookup('env', 'GITHUB_SHA') | default('master', True) }}"
|
||||
- name: update to newest paperless-ng release
|
||||
include_role:
|
||||
name: ansible
|
35
ansible/molecule/default/molecule.yml
Normal file
@@ -0,0 +1,35 @@
|
||||
---
|
||||
dependency:
|
||||
name: galaxy
|
||||
driver:
|
||||
name: docker
|
||||
platforms:
|
||||
- name: ubuntu_focal
|
||||
image: jrei/systemd-ubuntu:20.04
|
||||
privileged: true
|
||||
volumes:
|
||||
- /sys/fs/cgroup:/sys/fs/cgroup:ro
|
||||
tmpfs:
|
||||
- /tmp
|
||||
- /run
|
||||
- /run/lock
|
||||
override_command: False
|
||||
# ubuntu 18.04 bionic works except that
|
||||
# the default redis configuration expects IPv6 which is not enabled in docker by default
|
||||
# the default Python environment is configured for ASCII instead of UTF-8
|
||||
# ubuntu 16.04 xenial only has Python 3.5 which is EOL and breaks multiple dependencies
|
||||
- name: debian_buster
|
||||
image: jrei/systemd-debian:10
|
||||
privileged: true
|
||||
volumes:
|
||||
- /sys/fs/cgroup:/sys/fs/cgroup:ro
|
||||
tmpfs:
|
||||
- /tmp
|
||||
- /run
|
||||
- /run/lock
|
||||
override_command: False
|
||||
# debian 9 stretch only has Python 3.5 which is EOL and breaks multiple dependencies
|
||||
provisioner:
|
||||
name: ansible
|
||||
verifier:
|
||||
name: ansible
|
10
ansible/molecule/default/prepare.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
- name: install previous release
|
||||
hosts: all
|
||||
tasks:
|
||||
- name: set previous version as installation target
|
||||
set_fact:
|
||||
paperlessng_version: latest
|
||||
|
||||
- name: install previous paperless-ng release
|
||||
include_role:
|
||||
name: ansible
|
94
ansible/molecule/default/verify.yml
Normal file
@@ -0,0 +1,94 @@
|
||||
---
|
||||
- name: Verify
|
||||
hosts: all
|
||||
gather_facts: false
|
||||
|
||||
vars_files:
|
||||
- ../../defaults/main.yml
|
||||
|
||||
tasks:
|
||||
- name: check if webserver is up
|
||||
uri:
|
||||
url: "http://{{ paperlessng_listen_address }}:{{ paperlessng_listen_port }}"
|
||||
status_code: [200, 302]
|
||||
return_content: yes
|
||||
register: landingpage
|
||||
failed_when: "'Sign in</button>' not in landingpage.content"
|
||||
|
||||
- name: generate random name and content
|
||||
set_fact:
|
||||
content: "{{ lookup('password', '/dev/null length=65536 chars=ascii_letters') }}"
|
||||
filename: "{{ lookup('password', '/dev/null length=8 chars=ascii_letters') }}"
|
||||
|
||||
- name: check if document posting works
|
||||
uri:
|
||||
url: "http://{{ paperlessng_listen_address }}:{{ paperlessng_listen_port }}/api/documents/post_document/"
|
||||
method: POST
|
||||
body_format: form-multipart
|
||||
body:
|
||||
document:
|
||||
content: "{{ content }}"
|
||||
filename: "{{ filename }}.txt"
|
||||
headers:
|
||||
Authorization: 'Basic {{ (paperlessng_superuser_name + ":" + paperlessng_superuser_password) | b64encode }}'
|
||||
Content-Type: text/plain
|
||||
return_content: yes
|
||||
register: post_document
|
||||
failed_when: "'OK' not in post_document.content"
|
||||
|
||||
- name: verify uploaded document has been accepted
|
||||
uri:
|
||||
url: "http://{{ paperlessng_listen_address }}:{{ paperlessng_listen_port }}/api/logs/paperless/"
|
||||
headers:
|
||||
Authorization: 'Basic {{ (paperlessng_superuser_name + ":" + paperlessng_superuser_password) | b64encode }}'
|
||||
return_content: yes
|
||||
register: logs
|
||||
failed_when: "('Consuming ' + filename + '.txt') not in logs.content"
|
||||
|
||||
- name: sleep till consumption finished
|
||||
pause:
|
||||
seconds: 10
|
||||
|
||||
- name: verify uploaded document has been consumed
|
||||
uri:
|
||||
url: "http://{{ paperlessng_listen_address }}:{{ paperlessng_listen_port }}/api/logs/paperless/"
|
||||
headers:
|
||||
Authorization: 'Basic {{ (paperlessng_superuser_name + ":" + paperlessng_superuser_password) | b64encode }}'
|
||||
return_content: yes
|
||||
register: logs
|
||||
failed_when: "filename + ' consumption finished' not in logs.content"
|
||||
|
||||
- name: get documents
|
||||
uri:
|
||||
url: "http://{{ paperlessng_listen_address }}:{{ paperlessng_listen_port }}/api/documents/"
|
||||
headers:
|
||||
Authorization: 'Basic {{ (paperlessng_superuser_name + ":" + paperlessng_superuser_password) | b64encode }}'
|
||||
return_content: yes
|
||||
register: documents
|
||||
|
||||
- name: set document index
|
||||
set_fact:
|
||||
index: "{{ documents.json['results'][0]['id'] }}"
|
||||
|
||||
- name: verify uploaded document is avaiable
|
||||
uri:
|
||||
url: "http://{{ paperlessng_listen_address }}:{{ paperlessng_listen_port }}/api/documents/{{ index }}/"
|
||||
headers:
|
||||
Authorization: 'Basic {{ (paperlessng_superuser_name + ":" + paperlessng_superuser_password) | b64encode }}'
|
||||
return_content: yes
|
||||
register: document
|
||||
failed_when: "'Not found.' in document.content or content not in document.json['content']"
|
||||
|
||||
- name: check if deleting uploaded document works
|
||||
uri:
|
||||
url: "http://{{ paperlessng_listen_address }}:{{ paperlessng_listen_port }}/api/documents/bulk_edit/"
|
||||
method: POST
|
||||
body_format: json
|
||||
body:
|
||||
documents: ["{{ index }}"]
|
||||
method: delete
|
||||
parameters: {}
|
||||
headers:
|
||||
Authorization: 'Basic {{ (paperlessng_superuser_name + ":" + paperlessng_superuser_password) | b64encode }}'
|
||||
register: delete_document
|
||||
failed_when: "'OK' not in delete_document.json['result']"
|
6
ansible/tasks/install-release.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
- name: extract paperless-ng
|
||||
unarchive:
|
||||
src: "https://github.com/jonaswinkler/paperless-ng/releases/download/ng-{{ paperlessng_version }}/paperless-ng-{{ paperlessng_version }}.tar.xz"
|
||||
remote_src: yes
|
||||
dest: "{{ tempdir.path }}"
|
112
ansible/tasks/install-source.yml
Normal file
@@ -0,0 +1,112 @@
|
||||
---
|
||||
- name: install dev dependencies
|
||||
apt:
|
||||
pkg:
|
||||
- git
|
||||
- npm
|
||||
- gettext
|
||||
|
||||
- name: create output directories
|
||||
file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
owner: "{{ paperlessng_system_user }}"
|
||||
group: "{{ paperlessng_system_group }}"
|
||||
mode: "750"
|
||||
with_items:
|
||||
- "{{ tempdir.path }}/paperless-ng"
|
||||
- "{{ tempdir.path }}/paperless-ng/scripts"
|
||||
|
||||
- block:
|
||||
- name: create temporary git directory
|
||||
tempfile:
|
||||
state: directory
|
||||
path: "{{ paperlessng_directory }}"
|
||||
register: gitdir
|
||||
|
||||
- name: pull paperless-ng
|
||||
git:
|
||||
repo: https://github.com/jonaswinkler/paperless-ng.git
|
||||
dest: "{{ gitdir.path }}"
|
||||
version: "{{ paperlessng_version }}"
|
||||
refspec: "+refs/pull/*:refs/pull/*"
|
||||
|
||||
- name: compile frontend
|
||||
command:
|
||||
cmd: "{{ item }}"
|
||||
args:
|
||||
chdir: "{{ gitdir.path }}/src-ui"
|
||||
failed_when: false
|
||||
with_items:
|
||||
- npm install -g @angular/cli
|
||||
- npm install
|
||||
- ./node_modules/.bin/ng build --prod
|
||||
|
||||
- name: copy application into place
|
||||
copy:
|
||||
src: "{{ gitdir.path }}/{{ item.src }}"
|
||||
remote_src: yes
|
||||
dest: "{{ tempdir.path }}/paperless-ng/{{ item.dest | default('') }}"
|
||||
with_items:
|
||||
- src: CONTRIBUTING.md
|
||||
- src: LICENSE
|
||||
- src: Pipfile
|
||||
- src: Pipfile.lock
|
||||
- src: README.md
|
||||
- src: requirements.txt
|
||||
- src: gunicorn.conf.py
|
||||
- src: paperless.conf.example
|
||||
dest: "paperless.conf"
|
||||
|
||||
- name: glob all scripts
|
||||
find:
|
||||
paths: ["{{ gitdir.path }}/scripts/"]
|
||||
patterns:
|
||||
- "*.service"
|
||||
- "*.sh"
|
||||
register: glob
|
||||
|
||||
- name: copy scripts
|
||||
copy:
|
||||
src: "{{ item.path }}"
|
||||
remote_src: yes
|
||||
dest: "{{ tempdir.path }}/paperless-ng/scripts/"
|
||||
with_items:
|
||||
- "{{ glob.files }}"
|
||||
|
||||
- name: copy sources
|
||||
command:
|
||||
cmd: "cp -r src/ {{ tempdir.path }}/paperless-ng/src"
|
||||
args:
|
||||
chdir: "{{ gitdir.path }}"
|
||||
|
||||
- name: create paperlessng venv
|
||||
command:
|
||||
cmd: "python3 -m virtualenv {{ gitdir.path }}/.venv/ -p /usr/bin/python3"
|
||||
|
||||
- name: install paperlessng requirements
|
||||
command:
|
||||
cmd: "{{ gitdir.path }}/.venv/bin/python3 -m pip install -r {{ gitdir.path }}/requirements.txt"
|
||||
|
||||
- name: compile messages
|
||||
command: "{{ gitdir.path }}/.venv/bin/python3 manage.py compilemessages"
|
||||
args:
|
||||
chdir: "{{ tempdir.path }}/paperless-ng/src/"
|
||||
|
||||
- name: collect static files
|
||||
command: "{{ gitdir.path }}/.venv/bin/python3 manage.py collectstatic --no-input"
|
||||
args:
|
||||
chdir: "{{ tempdir.path }}/paperless-ng/src/"
|
||||
|
||||
- name: remove pycache directories
|
||||
shell: find . -name __pycache__ | xargs rm -r
|
||||
args:
|
||||
chdir: "{{ tempdir.path }}"
|
||||
|
||||
- name: remove temporary git directory
|
||||
file:
|
||||
path: "{{ gitdir.path }}"
|
||||
state: absent
|
||||
|
||||
become: yes
|
||||
become_user: "{{ paperlessng_system_user }}"
|
539
ansible/tasks/main.yml
Normal file
@@ -0,0 +1,539 @@
|
||||
---
|
||||
- name: verify operating system
|
||||
fail:
|
||||
msg: Sorry, only Debian and Ubuntu supported at the moment.
|
||||
when: not(ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu')
|
||||
|
||||
- name: install base dependencies
|
||||
apt:
|
||||
update_cache: yes
|
||||
pkg:
|
||||
# paperless-ng
|
||||
- python3-pip
|
||||
- python3-dev
|
||||
- fonts-liberation
|
||||
- imagemagick
|
||||
- optipng
|
||||
- gnupg
|
||||
- libpq-dev
|
||||
- libmagic-dev
|
||||
- mime-support
|
||||
# OCRmyPDF
|
||||
- unpaper
|
||||
- ghostscript
|
||||
- icc-profiles-free
|
||||
- qpdf
|
||||
- liblept5
|
||||
- libxml2
|
||||
- pngquant
|
||||
- zlib1g
|
||||
- tesseract-ocr
|
||||
# dev
|
||||
- sudo
|
||||
- build-essential
|
||||
- python3-setuptools
|
||||
- python3-wheel
|
||||
|
||||
# upstream virtualenv in Ubuntu 20.04 is broken
|
||||
# https://github.com/pypa/virtualenv/issues/1873
|
||||
- name: install python virtualenv
|
||||
pip:
|
||||
name: virtualenv
|
||||
extra_args: --upgrade
|
||||
|
||||
- name: install ocr languages
|
||||
apt:
|
||||
pkg: "{{ paperlessng_ocr_languages | map('regex_replace', '^(.*)$', 'tesseract-ocr-\\1') | list }}"
|
||||
|
||||
- name: set up notesalexp repository key (for jbig2enc)
|
||||
apt_key:
|
||||
url: https://notesalexp.org/debian/alexp_key.asc
|
||||
state: present
|
||||
when: paperlessng_use_jbig2enc
|
||||
|
||||
- name: set up notesalexp repository (for jbig2enc)
|
||||
apt_repository:
|
||||
repo: "deb https://notesalexp.org/debian/{{ ansible_distribution_release }}/ {{ ansible_distribution_release }} main"
|
||||
state: present
|
||||
when: paperlessng_use_jbig2enc
|
||||
|
||||
- name: set up notesalexp repository pinning
|
||||
copy:
|
||||
content: |
|
||||
Package: *
|
||||
Pin: release o=notesalexp.org
|
||||
Pin-Priority: 1
|
||||
|
||||
Package: jbig2enc
|
||||
Pin: release o=notesalexp.org
|
||||
Pin-Priority: 500
|
||||
dest: /etc/apt/preferences.d/notesalexp
|
||||
when: paperlessng_use_jbig2enc
|
||||
|
||||
- name: install jbig2enc
|
||||
apt:
|
||||
pkg: jbig2enc
|
||||
update_cache: yes
|
||||
when: paperlessng_use_jbig2enc
|
||||
|
||||
- name: install redis
|
||||
apt:
|
||||
pkg: redis-server
|
||||
when: paperlessng_redis_host == 'localhost' or paperlessng_redis_host == '127.0.0.1'
|
||||
|
||||
- name: enable redis
|
||||
systemd:
|
||||
name: redis-server
|
||||
enabled: yes
|
||||
masked: no
|
||||
state: started
|
||||
when: paperlessng_redis_host == 'localhost' or paperlessng_redis_host == '127.0.0.1'
|
||||
|
||||
- name: create paperless system group
|
||||
group:
|
||||
name: "{{ paperlessng_system_group }}"
|
||||
|
||||
- name: create paperless system user
|
||||
user:
|
||||
name: "{{ paperlessng_system_user }}"
|
||||
groups:
|
||||
- "{{ paperlessng_system_group }}"
|
||||
shell: /usr/sbin/nologin
|
||||
# GNUPG_HOME required due to paperless db.py
|
||||
create_home: yes
|
||||
|
||||
- block:
|
||||
- name: get latest release version
|
||||
uri:
|
||||
url: https://api.github.com/repos/jonaswinkler/paperless-ng/releases/latest
|
||||
method: GET
|
||||
register: latest_release
|
||||
- name: parse latest release version
|
||||
set_fact:
|
||||
paperlessng_version: "{{ latest_release.json['tag_name'] }}"
|
||||
when: paperlessng_version == "latest"
|
||||
|
||||
- name: check if version is ref
|
||||
fail:
|
||||
msg: "Specifying `paperlessng_version` as git ref may not work as expected!"
|
||||
ignore_errors: True # Output failure (as warning), but don't consider play failed
|
||||
when: paperlessng_version.startswith('refs/')
|
||||
|
||||
- block:
|
||||
- name: sanitize version string
|
||||
set_fact:
|
||||
paperlessng_version: "{{ paperlessng_version | regex_replace('^ng-(\\d+\\.\\d+\\.\\d+)$', '\\1') }}"
|
||||
- name: get tag data
|
||||
uri:
|
||||
url: https://api.github.com/repos/jonaswinkler/paperless-ng/tags
|
||||
method: GET
|
||||
register: tags
|
||||
- name: get commit for target tag
|
||||
set_fact:
|
||||
paperlessng_commit: "{{ tags.json | json_query('[?name==`ng-' + paperlessng_version +'`] | [0].commit.sha') }}"
|
||||
when: paperlessng_version | regex_search("^(ng-)?(\d+\.\d+\.\d+)$")
|
||||
|
||||
- block:
|
||||
- name: check if version is branch
|
||||
uri:
|
||||
url: "https://api.github.com/repos/jonaswinkler/paperless-ng/branches/{{ paperlessng_version }}"
|
||||
method: GET
|
||||
status_code: [200, 404]
|
||||
register: branch
|
||||
- name: get commit for target branch
|
||||
set_fact:
|
||||
paperlessng_commit: "{{ branch.json | json_query('commit.sha') }}"
|
||||
when: branch.status == 200
|
||||
- block:
|
||||
- name: check if version is commit-or-ref
|
||||
uri:
|
||||
url: "https://api.github.com/repos/jonaswinkler/paperless-ng/commits/{{ paperlessng_version }}"
|
||||
method: GET
|
||||
status_code: [200, 404, 422]
|
||||
register: commit
|
||||
- name: get commit for target commit-or-ref
|
||||
set_fact:
|
||||
paperlessng_commit: "{{ commit.json | json_query('sha') }}"
|
||||
when: commit.status == 200
|
||||
- name: fail
|
||||
fail:
|
||||
msg: "Can not determine commit from `paperlessng_version=={{ paperlessng_version }}`!"
|
||||
when: commit.status != 200
|
||||
when: branch.status == 404
|
||||
when: not(paperlessng_version | regex_search("^(ng-)?(\d+\.\d+\.\d+)$"))
|
||||
|
||||
- name: check for paperless-ng installation
|
||||
command:
|
||||
cmd: "cat {{ paperlessng_directory }}/.installed_version"
|
||||
changed_when: '"No such file or directory" in paperlessng_current_commit.stderr or paperlessng_current_commit.stdout != paperlessng_commit | string'
|
||||
failed_when: false
|
||||
ignore_errors: yes
|
||||
register: paperlessng_current_commit
|
||||
|
||||
- name: register current state
|
||||
set_fact:
|
||||
fresh_installation: '{{ "No such file or directory" in paperlessng_current_commit.stderr }}'
|
||||
update_installation: '{{ "No such file or directory" not in paperlessng_current_commit.stderr and paperlessng_current_commit.stdout != paperlessng_commit | string }}'
|
||||
reconfigure_only: "{{ paperlessng_current_commit.stdout == paperlessng_commit | string }}"
|
||||
|
||||
- block:
|
||||
- name: backup current paperless-ng installation
|
||||
copy:
|
||||
src: "{{ paperlessng_directory }}"
|
||||
remote_src: yes
|
||||
dest: "{{ paperlessng_directory }}-{{ ansible_date_time.iso8601 }}/"
|
||||
- name: remove current paperless sources
|
||||
file:
|
||||
path: "{{ paperlessng_directory }}/{{ item }}"
|
||||
state: absent
|
||||
with_items:
|
||||
- docker
|
||||
- docs
|
||||
- scripts
|
||||
- src
|
||||
- static
|
||||
when: update_installation
|
||||
|
||||
- block:
|
||||
- name: create paperless-ng directory and set permissions
|
||||
file:
|
||||
path: "{{ paperlessng_directory }}"
|
||||
state: directory
|
||||
owner: "{{ paperlessng_system_user }}"
|
||||
group: "{{ paperlessng_system_group }}"
|
||||
mode: "750"
|
||||
- name: create temporary directory
|
||||
become: yes
|
||||
become_user: "{{ paperlessng_system_user }}"
|
||||
tempfile:
|
||||
state: directory
|
||||
path: "{{ paperlessng_directory }}"
|
||||
register: tempdir
|
||||
- name: check if version is available as release archive
|
||||
uri:
|
||||
url: "https://github.com/jonaswinkler/paperless-ng/releases/download/ng-{{ paperlessng_version }}/paperless-ng-{{ paperlessng_version }}.tar.xz"
|
||||
method: GET
|
||||
status_code: [200, 404]
|
||||
register: release_archive
|
||||
- name: install paperless-ng from source
|
||||
include_tasks: install-source.yml
|
||||
when: release_archive.status == 404
|
||||
- name: install paperless-ng from release archive
|
||||
include_tasks: install-release.yml
|
||||
when: release_archive.status == 200
|
||||
- name: change owner and permissions of paperless-ng
|
||||
command:
|
||||
cmd: "{{ item }}"
|
||||
warn: false
|
||||
with_items:
|
||||
- "chown -R {{ paperlessng_system_user }}:{{ paperlessng_system_group }} {{ tempdir.path }}"
|
||||
- "find {{ tempdir.path }} -type d -exec chmod 0750 {} ;"
|
||||
- "find {{ tempdir.path }} -type f -exec chmod 0640 {} ;"
|
||||
- name: move paperless-ng
|
||||
command:
|
||||
cmd: "cp -a {{ tempdir.path }}/paperless-ng/. {{ paperlessng_directory }}"
|
||||
- name: store commit hash of installed version
|
||||
copy:
|
||||
content: "{{ paperlessng_commit }}"
|
||||
dest: "{{ paperlessng_directory }}/.installed_version"
|
||||
owner: "{{ paperlessng_system_user }}"
|
||||
group: "{{ paperlessng_system_group }}"
|
||||
mode: "0440"
|
||||
- name: remove temporary directory
|
||||
file:
|
||||
path: "{{ tempdir.path }}"
|
||||
state: absent
|
||||
when: not reconfigure_only
|
||||
|
||||
- name: create paperless-ng directories and set permissions
|
||||
file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
owner: "{{ paperlessng_system_user }}"
|
||||
group: "{{ paperlessng_system_group }}"
|
||||
mode: "750"
|
||||
with_items:
|
||||
- "{{ paperlessng_consumption_dir }}"
|
||||
- "{{ paperlessng_data_dir }}"
|
||||
- "{{ paperlessng_media_root }}"
|
||||
- "{{ paperlessng_static_dir }}"
|
||||
|
||||
- name: rename initial config
|
||||
command:
|
||||
cmd: "mv -f {{ paperlessng_directory }}/paperless.conf {{ paperlessng_directory }}/paperless.conf.template"
|
||||
removes: "{{ paperlessng_directory }}/paperless.conf"
|
||||
|
||||
- name: configure paperless-ng
|
||||
lineinfile:
|
||||
path: "{{ paperlessng_directory }}/paperless.conf.template"
|
||||
regexp: "^#?{{ item.regexp }}="
|
||||
line: "{{ item.line }}"
|
||||
with_items:
|
||||
# Required services
|
||||
- regexp: PAPERLESS_REDIS
|
||||
line: "PAPERLESS_REDIS=redis://{{ paperlessng_redis_host }}:{{ paperlessng_redis_port }}"
|
||||
# Paths and folders
|
||||
- regexp: PAPERLESS_CONSUMPTION_DIR
|
||||
line: "PAPERLESS_CONSUMPTION_DIR={{ paperlessng_consumption_dir }}"
|
||||
- regexp: PAPERLESS_DATA_DIR
|
||||
line: "PAPERLESS_DATA_DIR={{ paperlessng_data_dir }}"
|
||||
- regexp: PAPERLESS_MEDIA_ROOT
|
||||
line: "PAPERLESS_MEDIA_ROOT={{ paperlessng_media_root }}"
|
||||
- regexp: PAPERLESS_STATICDIR
|
||||
line: "PAPERLESS_STATICDIR={{ paperlessng_static_dir }}"
|
||||
- regexp: PAPERLESS_FILENAME_FORMAT
|
||||
line: "PAPERLESS_FILENAME_FORMAT={{ paperlessng_filename_format }}"
|
||||
# Hosting & Security
|
||||
- regexp: PAPERLESS_SECRET_KEY
|
||||
line: "PAPERLESS_SECRET_KEY={{ paperlessng_secret_key }}"
|
||||
- regexp: PAPERLESS_ALLOWED_HOSTS
|
||||
line: "PAPERLESS_ALLOWED_HOSTS={{ paperlessng_allowed_hosts }}"
|
||||
- regexp: PAPERLESS_CORS_ALLOWED_HOSTS
|
||||
line: "PAPERLESS_CORS_ALLOWED_HOSTS={{ paperlessng_cors_allowed_hosts }}"
|
||||
- regexp: PAPERLESS_FORCE_SCRIPT_NAME
|
||||
line: "PAPERLESS_FORCE_SCRIPT_NAME={{ paperlessng_force_script_name }}"
|
||||
- regexp: PAPERLESS_STATIC_URL
|
||||
line: "PAPERLESS_STATIC_URL={{ paperlessng_static_url }}"
|
||||
- regexp: PAPERLESS_AUTO_LOGIN_USERNAME
|
||||
line: "PAPERLESS_AUTO_LOGIN_USERNAME={{ paperlessng_auto_login_username }}"
|
||||
- regexp: PAPERLESS_COOKIE_PREFIX
|
||||
line: "PAPERLESS_COOKIE_PREFIX={{ paperlessng_cookie_prefix }}"
|
||||
- regexp: PAPERLESS_ENABLE_HTTP_REMOTE_USER
|
||||
line: "PAPERLESS_ENABLE_HTTP_REMOTE_USER={{ paperlessng_enable_http_remote_user }}"
|
||||
# OCR settings
|
||||
- regexp: PAPERLESS_OCR_LANGUAGE
|
||||
line: "PAPERLESS_OCR_LANGUAGE={{ paperlessng_ocr_languages | join('+') }}"
|
||||
- regexp: PAPERLESS_OCR_MODE
|
||||
line: "PAPERLESS_OCR_MODE={{ paperlessng_ocr_mode }}"
|
||||
- regexp: PAPERLESS_OCR_OUTPUT_TYPE
|
||||
line: "PAPERLESS_OCR_OUTPUT_TYPE={{ paperlessng_ocr_output_type }}"
|
||||
- regexp: PAPERLESS_OCR_PAGES
|
||||
line: "PAPERLESS_OCR_PAGES={{ paperlessng_ocr_pages }}"
|
||||
- regexp: PAPERLESS_OCR_IMAGE_DPI
|
||||
line: "PAPERLESS_OCR_IMAGE_DPI={{ paperlessng_ocr_image_dpi }}"
|
||||
- regexp: PAPERLESS_OCR_USER_ARGS
|
||||
line: "PAPERLESS_OCR_USER_ARGS={{ paperlessng_ocr_user_args | combine({'jbig2_lossy': true} if paperlessng_big2enc_lossy else {}) | to_json }}"
|
||||
# Tika settings
|
||||
- regexp: PAPERLESS_TIKA_ENABLED
|
||||
line: "PAPERLESS_TIKA_ENABLED={{ paperlessng_tika_enabled }}"
|
||||
- regexp: PAPERLESS_TIKA_ENDPOINT
|
||||
line: "PAPERLESS_TIKA_ENDPOINT={{ paperlessng_tika_endpoint }}"
|
||||
- regexp: PAPERLESS_TIKA_GOTENBERG_ENDPOINT
|
||||
line: "PAPERLESS_TIKA_GOTENBERG_ENDPOINT={{ paperlessng_tika_endpoint }}"
|
||||
# Software tweaks
|
||||
- regexp: PAPERLESS_TIME_ZONE
|
||||
line: "PAPERLESS_TIME_ZONE={{ paperlessng_time_zone }}"
|
||||
- regexp: PAPERLESS_CONSUMER_POLLING
|
||||
line: "PAPERLESS_CONSUMER_POLLING={{ paperlessng_consumer_polling }}"
|
||||
- regexp: PAPERLESS_CONSUMER_DELETE_DUPLICATES
|
||||
line: "PAPERLESS_CONSUMER_DELETE_DUPLICATES={{ paperlessng_consumer_delete_duplicates }}"
|
||||
- regexp: PAPERLESS_CONSUMER_RECURSIVE
|
||||
line: "PAPERLESS_CONSUMER_RECURSIVE={{ paperlessng_consumer_recursive }}"
|
||||
- regexp: PAPERLESS_CONSUMER_SUBDIRS_AS_TAGS
|
||||
line: "PAPERLESS_CONSUMER_SUBDIRS_AS_TAGS={{ paperlessng_consumer_subdirs_as_tags }}"
|
||||
- regexp: PAPERLESS_OPTIMIZE_THUMBNAILS
|
||||
line: "PAPERLESS_OPTIMIZE_THUMBNAILS={{ paperlessng_optimize_thumbnails }}"
|
||||
- regexp: PAPERLESS_POST_CONSUME_SCRIPT
|
||||
line: "PAPERLESS_POST_CONSUME_SCRIPT={{ paperlessng_post_consume_script }}"
|
||||
- regexp: PAPERLESS_FILENAME_DATE_ORDER
|
||||
line: "PAPERLESS_FILENAME_DATE_ORDER={{ paperlessng_filename_date_order }}"
|
||||
- regexp: PAPERLESS_THUMBNAIL_FONT_NAME
|
||||
line: "PAPERLESS_THUMBNAIL_FONT_NAME={{ paperlessng_thumbnail_font_name }}"
|
||||
- regexp: PAPERLESS_IGNORE_DATES
|
||||
line: "PAPERLESS_IGNORE_DATES={{ paperlessng_ignore_dates }}"
|
||||
no_log: yes
|
||||
|
||||
- name: configure paperless-ng database [sqlite]
|
||||
lineinfile:
|
||||
path: "{{ paperlessng_directory }}/paperless.conf.template"
|
||||
regexp: "^#?PAPERLESS_DBHOST=(.*)$"
|
||||
line: '#PAPERLESS_DBHOST=\1'
|
||||
backrefs: yes
|
||||
when: paperlessng_db_type == 'sqlite'
|
||||
|
||||
- name: configure paperless-ng database [postgresql]
|
||||
lineinfile:
|
||||
path: "{{ paperlessng_directory }}/paperless.conf.template"
|
||||
regexp: "^#?{{ item.regexp }}="
|
||||
line: "{{ item.line }}"
|
||||
with_items:
|
||||
- regexp: PAPERLESS_DBHOST
|
||||
line: "PAPERLESS_DBHOST={{ paperlessng_db_host }}"
|
||||
- regexp: PAPERLESS_DBPORT
|
||||
line: "PAPERLESS_DBPORT={{ paperlessng_db_port }}"
|
||||
- regexp: PAPERLESS_DBNAME
|
||||
line: "PAPERLESS_DBNAME={{ paperlessng_db_name }}"
|
||||
- regexp: PAPERLESS_DBUSER
|
||||
line: "PAPERLESS_DBUSER={{ paperlessng_db_user }}"
|
||||
- regexp: PAPERLESS_DBPASS
|
||||
line: "PAPERLESS_DBPASS={{ paperlessng_db_pass }}"
|
||||
- regexp: PAPERLESS_DBSSLMODE
|
||||
line: "PAPERLESS_DBSSLMODE={{ paperlessng_db_sslmode }}"
|
||||
when: paperlessng_db_type == 'postgresql'
|
||||
no_log: yes
|
||||
|
||||
- name: deploy paperless-ng configuration
|
||||
copy:
|
||||
src: "{{ paperlessng_directory }}/paperless.conf.template"
|
||||
remote_src: yes
|
||||
dest: /etc/paperless.conf
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
register: configuration
|
||||
|
||||
- name: create paperlessng venv
|
||||
become: yes
|
||||
become_user: "{{ paperlessng_system_user }}"
|
||||
command:
|
||||
cmd: "python3 -m virtualenv {{ paperlessng_virtualenv }} -p /usr/bin/python3"
|
||||
creates: "{{ paperlessng_virtualenv }}"
|
||||
register: venv
|
||||
|
||||
- block:
|
||||
- name: install paperlessng requirements
|
||||
become: yes
|
||||
become_user: "{{ paperlessng_system_user }}"
|
||||
pip:
|
||||
requirements: "{{ paperlessng_directory }}/requirements.txt"
|
||||
executable: "{{ paperlessng_virtualenv }}/bin/pip3"
|
||||
extra_args: --upgrade
|
||||
- name: migrate database schema
|
||||
become: yes
|
||||
become_user: "{{ paperlessng_system_user }}"
|
||||
command: "{{ paperlessng_virtualenv }}/bin/python3 {{ paperlessng_directory }}/src/manage.py migrate"
|
||||
register: database_schema
|
||||
changed_when: '"No migrations to apply." not in database_schema.stdout'
|
||||
when: not reconfigure_only
|
||||
|
||||
- name: configure paperless superuser
|
||||
become: yes
|
||||
become_user: "{{ paperlessng_system_user }}"
|
||||
# "manage.py createsuperuser" only works on interactive TTYs
|
||||
vars:
|
||||
creation_script: |
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.auth.hashers import get_hasher
|
||||
|
||||
if User.objects.filter(username='{{ paperlessng_superuser_name }}').exists():
|
||||
user = User.objects.get(username='{{ paperlessng_superuser_name }}')
|
||||
old = user.__dict__.copy()
|
||||
|
||||
user.is_superuser = True
|
||||
user.email = '{{ paperlessng_superuser_email }}'
|
||||
user.set_password('{{ paperlessng_superuser_password }}')
|
||||
user.save()
|
||||
new = user.__dict__
|
||||
|
||||
algorithm, iterations, old_salt, old_hash = old['password'].split('$')
|
||||
new_password_old_salt = get_hasher(algorithm).encode(password='{{ paperlessng_superuser_password }}', salt=old_salt, iterations=int(iterations))
|
||||
_, _, _, new_hash = new_password_old_salt.split('$')
|
||||
if not (old_hash == new_hash and old['is_superuser'] == new['is_superuser'] and old['email'] == new['email']):
|
||||
print('changed')
|
||||
else:
|
||||
User.objects.create_superuser('{{ paperlessng_superuser_name }}', '{{ paperlessng_superuser_email }}', '{{ paperlessng_superuser_password }}')
|
||||
print('changed')
|
||||
command: '{{ paperlessng_virtualenv }}/bin/python3 {{ paperlessng_directory }}/src/manage.py shell -c "{{ creation_script }}"'
|
||||
register: superuser
|
||||
changed_when: superuser.stdout == 'changed'
|
||||
no_log: yes
|
||||
|
||||
- name: set ownership and permissions on paperlessng venv
|
||||
file:
|
||||
path: "{{ paperlessng_virtualenv }}"
|
||||
state: directory
|
||||
recurse: yes
|
||||
owner: "{{ paperlessng_system_user }}"
|
||||
group: "{{ paperlessng_system_group }}"
|
||||
mode: g-w,o-rwx
|
||||
when: venv.changed or not reconfigure_only
|
||||
|
||||
- name: configure ghostscript for PDF
|
||||
lineinfile:
|
||||
path: /etc/ImageMagick-6/policy.xml
|
||||
regexp: '(\s+)<policy domain="coder" rights=".*" pattern="PDF" />'
|
||||
line: '\1<policy domain="coder" rights="read|write" pattern="PDF" />'
|
||||
backrefs: yes
|
||||
|
||||
- name: configure gunicorn web server
|
||||
lineinfile:
|
||||
path: "{{ paperlessng_directory }}/gunicorn.conf.py"
|
||||
regexp: '^bind = '
|
||||
line: "bind = '{{ paperlessng_listen_address }}:{{ paperlessng_listen_port }}'"
|
||||
|
||||
- name: configure systemd services
|
||||
ini_file:
|
||||
path: "{{ paperlessng_directory }}/scripts/{{ item[0] }}"
|
||||
section: "Service"
|
||||
option: "{{ item[1].option }}"
|
||||
value: "{{ item[1].value }}"
|
||||
with_nested:
|
||||
- [
|
||||
paperless-consumer.service,
|
||||
paperless-scheduler.service,
|
||||
paperless-webserver.service,
|
||||
]
|
||||
- [
|
||||
# https://www.freedesktop.org/software/systemd/man/systemd.exec.html
|
||||
{ option: "User", value: "{{ paperlessng_system_user }}" },
|
||||
{ option: "Group", value: "{{ paperlessng_system_group }}" },
|
||||
{ option: "WorkingDirectory", value: "{{ paperlessng_directory }}/src" },
|
||||
{ option: "ProtectSystem", value: "full" },
|
||||
{ option: "NoNewPrivileges", value: "true" },
|
||||
{ option: "PrivateUsers", value: "true" },
|
||||
{ option: "PrivateDevices", value: "true" },
|
||||
]
|
||||
|
||||
- name: configure paperless-consumer service
|
||||
ini_file:
|
||||
path: "{{ paperlessng_directory }}/scripts/paperless-consumer.service"
|
||||
section: "Service"
|
||||
option: "ExecStart"
|
||||
value: "{{ paperlessng_virtualenv }}/bin/python3 manage.py document_consumer"
|
||||
|
||||
- name: configure paperless-scheduler service
|
||||
ini_file:
|
||||
path: "{{ paperlessng_directory }}/scripts/paperless-scheduler.service"
|
||||
section: "Service"
|
||||
option: "ExecStart"
|
||||
value: "{{ paperlessng_virtualenv }}/bin/python3 manage.py qcluster"
|
||||
|
||||
- name: configure paperless-webserver service
|
||||
ini_file:
|
||||
path: "{{ paperlessng_directory }}/scripts/paperless-webserver.service"
|
||||
section: "Service"
|
||||
option: "ExecStart"
|
||||
value: "{{ paperlessng_virtualenv }}/bin/gunicorn -c {{ paperlessng_directory }}/gunicorn.conf.py paperless.asgi:application"
|
||||
|
||||
- name: copy systemd services
|
||||
copy:
|
||||
src: "{{ paperlessng_directory }}/scripts/{{ item }}"
|
||||
remote_src: yes
|
||||
dest: "/etc/systemd/system/{{ item }}"
|
||||
with_items:
|
||||
- paperless-consumer.service
|
||||
- paperless-scheduler.service
|
||||
- paperless-webserver.service
|
||||
register: paperless_services
|
||||
|
||||
- name: reload systemd daemon
|
||||
systemd:
|
||||
name: "{{ item }}"
|
||||
state: restarted
|
||||
daemon_reload: yes
|
||||
with_items:
|
||||
- paperless-consumer
|
||||
- paperless-scheduler
|
||||
- paperless-webserver
|
||||
when: paperless_services.changed or configuration.changed
|
||||
|
||||
- name: enable paperlessng services
|
||||
systemd:
|
||||
name: "{{ item }}"
|
||||
enabled: yes
|
||||
masked: no
|
||||
state: started
|
||||
with_items:
|
||||
- paperless-consumer
|
||||
- paperless-scheduler
|
||||
- paperless-webserver
|
7
compile-frontend.sh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
cd src-ui
|
||||
npm install
|
||||
./node_modules/.bin/ng build --prod
|
5
crowdin.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
files:
|
||||
- source: /src/locale/en_US/LC_MESSAGES/django.po
|
||||
translation: /src/locale/%locale_with_underscore%/LC_MESSAGES/django.po
|
||||
- source: /src-ui/messages.xlf
|
||||
translation: /src-ui/src/locale/messages.%locale_with_underscore%.xlf
|
1
docker/compose/.env
Normal file
@@ -0,0 +1 @@
|
||||
COMPOSE_PROJECT_NAME=paperless
|
@@ -7,7 +7,7 @@
|
||||
# Additional languages to install for text recognition, separated by a
|
||||
# whitespace. Note that this is
|
||||
# different from PAPERLESS_OCR_LANGUAGE (default=eng), which defines the
|
||||
# default language used when guessing the language from the OCR output.
|
||||
# language used for OCR.
|
||||
# The container installs English, German, Italian, Spanish and French by
|
||||
# default.
|
||||
# See https://packages.debian.org/search?keywords=tesseract-ocr-&searchon=names&suite=buster
|
||||
@@ -32,8 +32,3 @@
|
||||
# The default language to use for OCR. Set this to the language most of your
|
||||
# documents are written in.
|
||||
#PAPERLESS_OCR_LANGUAGE=eng
|
||||
|
||||
# By default Paperless does not OCR a document if the text can be retrieved from
|
||||
# the document directly. Set to true to always OCR documents. (i.e., if you
|
||||
# know that some of your documents have faulty/bad OCR data)
|
||||
#PAPERLESS_OCR_ALWAYS=true
|
90
docker/compose/docker-compose.postgres-tika.yml
Normal file
@@ -0,0 +1,90 @@
|
||||
# docker-compose file for running paperless from the Docker Hub.
|
||||
# This file contains everything paperless needs to run.
|
||||
# Paperless supports amd64, arm and arm64 hardware.
|
||||
#
|
||||
# All compose files of paperless configure paperless in the following way:
|
||||
#
|
||||
# - Paperless is (re)started on system boot, if it was running before shutdown.
|
||||
# - Docker volumes for storing data are managed by Docker.
|
||||
# - Folders for importing and exporting files are created in the same directory
|
||||
# as this file and mounted to the correct folders inside the container.
|
||||
# - Paperless listens on port 8000.
|
||||
#
|
||||
# In addition to that, this docker-compose file adds the following optional
|
||||
# configurations:
|
||||
#
|
||||
# - Instead of SQLite (default), PostgreSQL is used as the database server.
|
||||
# - Apache Tika and Gotenberg servers are started with paperless and paperless
|
||||
# is configured to use these services. These provide support for consuming
|
||||
# Office documents (Word, Excel, Power Point and their LibreOffice counter-
|
||||
# parts.
|
||||
#
|
||||
# To install and update paperless with this file, do the following:
|
||||
#
|
||||
# - Copy this file as 'docker-compose.yml' and the files 'docker-compose.env'
|
||||
# and '.env' into a folder.
|
||||
# - Run 'docker-compose pull'.
|
||||
# - Run 'docker-compose run --rm webserver createsuperuser' to create a user.
|
||||
# - Run 'docker-compose up -d'.
|
||||
#
|
||||
# For more extensive installation and update instructions, refer to the
|
||||
# documentation.
|
||||
|
||||
version: "3.4"
|
||||
services:
|
||||
broker:
|
||||
image: redis:6.0
|
||||
restart: unless-stopped
|
||||
|
||||
db:
|
||||
image: postgres:13
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- pgdata:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_DB: paperless
|
||||
POSTGRES_USER: paperless
|
||||
POSTGRES_PASSWORD: paperless
|
||||
|
||||
webserver:
|
||||
image: jonaswinkler/paperless-ng:latest
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- db
|
||||
- broker
|
||||
- gotenberg
|
||||
- tika
|
||||
ports:
|
||||
- 8000:8000
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
volumes:
|
||||
- data:/usr/src/paperless/data
|
||||
- media:/usr/src/paperless/media
|
||||
- ./export:/usr/src/paperless/export
|
||||
- ./consume:/usr/src/paperless/consume
|
||||
env_file: docker-compose.env
|
||||
environment:
|
||||
PAPERLESS_REDIS: redis://broker:6379
|
||||
PAPERLESS_DBHOST: db
|
||||
PAPERLESS_TIKA_ENABLED: 1
|
||||
PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000
|
||||
PAPERLESS_TIKA_ENDPOINT: http://tika:9998
|
||||
|
||||
gotenberg:
|
||||
image: thecodingmachine/gotenberg
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
DISABLE_GOOGLE_CHROME: 1
|
||||
|
||||
tika:
|
||||
image: apache/tika
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
data:
|
||||
media:
|
||||
pgdata:
|
72
docker/compose/docker-compose.postgres.yml
Normal file
@@ -0,0 +1,72 @@
|
||||
# docker-compose file for running paperless from the Docker Hub.
|
||||
# This file contains everything paperless needs to run.
|
||||
# Paperless supports amd64, arm and arm64 hardware.
|
||||
#
|
||||
# All compose files of paperless configure paperless in the following way:
|
||||
#
|
||||
# - Paperless is (re)started on system boot, if it was running before shutdown.
|
||||
# - Docker volumes for storing data are managed by Docker.
|
||||
# - Folders for importing and exporting files are created in the same directory
|
||||
# as this file and mounted to the correct folders inside the container.
|
||||
# - Paperless listens on port 8000.
|
||||
#
|
||||
# In addition to that, this docker-compose file adds the following optional
|
||||
# configurations:
|
||||
#
|
||||
# - Instead of SQLite (default), PostgreSQL is used as the database server.
|
||||
#
|
||||
# To install and update paperless with this file, do the following:
|
||||
#
|
||||
# - Copy this file as 'docker-compose.yml' and the files 'docker-compose.env'
|
||||
# and '.env' into a folder.
|
||||
# - Run 'docker-compose pull'.
|
||||
# - Run 'docker-compose run --rm webserver createsuperuser' to create a user.
|
||||
# - Run 'docker-compose up -d'.
|
||||
#
|
||||
# For more extensive installation and update instructions, refer to the
|
||||
# documentation.
|
||||
|
||||
version: "3.4"
|
||||
services:
|
||||
broker:
|
||||
image: redis:6.0
|
||||
restart: unless-stopped
|
||||
|
||||
db:
|
||||
image: postgres:13
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- pgdata:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_DB: paperless
|
||||
POSTGRES_USER: paperless
|
||||
POSTGRES_PASSWORD: paperless
|
||||
|
||||
webserver:
|
||||
image: jonaswinkler/paperless-ng:latest
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- db
|
||||
- broker
|
||||
ports:
|
||||
- 8000:8000
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
volumes:
|
||||
- data:/usr/src/paperless/data
|
||||
- media:/usr/src/paperless/media
|
||||
- ./export:/usr/src/paperless/export
|
||||
- ./consume:/usr/src/paperless/consume
|
||||
env_file: docker-compose.env
|
||||
environment:
|
||||
PAPERLESS_REDIS: redis://broker:6379
|
||||
PAPERLESS_DBHOST: db
|
||||
|
||||
|
||||
volumes:
|
||||
data:
|
||||
media:
|
||||
pgdata:
|
78
docker/compose/docker-compose.sqlite-tika.yml
Normal file
@@ -0,0 +1,78 @@
|
||||
# docker-compose file for running paperless from the Docker Hub.
|
||||
# This file contains everything paperless needs to run.
|
||||
# Paperless supports amd64, arm and arm64 hardware.
|
||||
#
|
||||
# All compose files of paperless configure paperless in the following way:
|
||||
#
|
||||
# - Paperless is (re)started on system boot, if it was running before shutdown.
|
||||
# - Docker volumes for storing data are managed by Docker.
|
||||
# - Folders for importing and exporting files are created in the same directory
|
||||
# as this file and mounted to the correct folders inside the container.
|
||||
# - Paperless listens on port 8000.
|
||||
#
|
||||
# SQLite is used as the database. The SQLite file is stored in the data volume.
|
||||
#
|
||||
# In addition to that, this docker-compose file adds the following optional
|
||||
# configurations:
|
||||
#
|
||||
# - Apache Tika and Gotenberg servers are started with paperless and paperless
|
||||
# is configured to use these services. These provide support for consuming
|
||||
# Office documents (Word, Excel, Power Point and their LibreOffice counter-
|
||||
# parts.
|
||||
#
|
||||
# To install and update paperless with this file, do the following:
|
||||
#
|
||||
# - Copy this file as 'docker-compose.yml' and the files 'docker-compose.env'
|
||||
# and '.env' into a folder.
|
||||
# - Run 'docker-compose pull'.
|
||||
# - Run 'docker-compose run --rm webserver createsuperuser' to create a user.
|
||||
# - Run 'docker-compose up -d'.
|
||||
#
|
||||
# For more extensive installation and update instructions, refer to the
|
||||
# documentation.
|
||||
|
||||
version: "3.4"
|
||||
services:
|
||||
broker:
|
||||
image: redis:6.0
|
||||
restart: unless-stopped
|
||||
|
||||
webserver:
|
||||
image: jonaswinkler/paperless-ng:latest
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- broker
|
||||
- gotenberg
|
||||
- tika
|
||||
ports:
|
||||
- 8000:8000
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
volumes:
|
||||
- data:/usr/src/paperless/data
|
||||
- media:/usr/src/paperless/media
|
||||
- ./export:/usr/src/paperless/export
|
||||
- ./consume:/usr/src/paperless/consume
|
||||
env_file: docker-compose.env
|
||||
environment:
|
||||
PAPERLESS_REDIS: redis://broker:6379
|
||||
PAPERLESS_TIKA_ENABLED: 1
|
||||
PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000
|
||||
PAPERLESS_TIKA_ENDPOINT: http://tika:9998
|
||||
|
||||
gotenberg:
|
||||
image: thecodingmachine/gotenberg
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
DISABLE_GOOGLE_CHROME: 1
|
||||
|
||||
tika:
|
||||
image: apache/tika
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
data:
|
||||
media:
|
56
docker/compose/docker-compose.sqlite.yml
Normal file
@@ -0,0 +1,56 @@
|
||||
# docker-compose file for running paperless from the Docker Hub.
|
||||
# This file contains everything paperless needs to run.
|
||||
# Paperless supports amd64, arm and arm64 hardware.
|
||||
#
|
||||
# All compose files of paperless configure paperless in the following way:
|
||||
#
|
||||
# - Paperless is (re)started on system boot, if it was running before shutdown.
|
||||
# - Docker volumes for storing data are managed by Docker.
|
||||
# - Folders for importing and exporting files are created in the same directory
|
||||
# as this file and mounted to the correct folders inside the container.
|
||||
# - Paperless listens on port 8000.
|
||||
#
|
||||
# SQLite is used as the database. The SQLite file is stored in the data volume.
|
||||
#
|
||||
# To install and update paperless with this file, do the following:
|
||||
#
|
||||
# - Copy this file as 'docker-compose.yml' and the files 'docker-compose.env'
|
||||
# and '.env' into a folder.
|
||||
# - Run 'docker-compose pull'.
|
||||
# - Run 'docker-compose run --rm webserver createsuperuser' to create a user.
|
||||
# - Run 'docker-compose up -d'.
|
||||
#
|
||||
# For more extensive installation and update instructions, refer to the
|
||||
# documentation.
|
||||
|
||||
version: "3.4"
|
||||
services:
|
||||
broker:
|
||||
image: redis:6.0
|
||||
restart: unless-stopped
|
||||
|
||||
webserver:
|
||||
image: jonaswinkler/paperless-ng:latest
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- broker
|
||||
ports:
|
||||
- 8000:8000
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
volumes:
|
||||
- data:/usr/src/paperless/data
|
||||
- media:/usr/src/paperless/media
|
||||
- ./export:/usr/src/paperless/export
|
||||
- ./consume:/usr/src/paperless/consume
|
||||
env_file: docker-compose.env
|
||||
environment:
|
||||
PAPERLESS_REDIS: redis://broker:6379
|
||||
|
||||
|
||||
volumes:
|
||||
data:
|
||||
media:
|
@@ -15,13 +15,54 @@ map_uidgid() {
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
wait_for_postgres() {
|
||||
attempt_num=1
|
||||
max_attempts=5
|
||||
|
||||
echo "Waiting for PostgreSQL to start..."
|
||||
|
||||
host="${PAPERLESS_DBHOST}"
|
||||
port="${PAPERLESS_DBPORT}"
|
||||
|
||||
if [[ -z $port ]] ;
|
||||
then
|
||||
port="5432"
|
||||
fi
|
||||
|
||||
while !</dev/tcp/$host/$port ;
|
||||
do
|
||||
|
||||
if [ $attempt_num -eq $max_attempts ]
|
||||
then
|
||||
echo "Unable to connect to database."
|
||||
exit 1
|
||||
else
|
||||
echo "Attempt $attempt_num failed! Trying again in 5 seconds..."
|
||||
|
||||
fi
|
||||
|
||||
attempt_num=$(expr "$attempt_num" + 1)
|
||||
sleep 5
|
||||
done
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
migrations() {
|
||||
|
||||
if [[ -n "${PAPERLESS_DBHOST}" ]]
|
||||
then
|
||||
wait_for_postgres
|
||||
fi
|
||||
|
||||
(
|
||||
# flock is in place to prevent multiple containers from doing migrations
|
||||
# simultaneously. This also ensures that the db is ready when the command
|
||||
# of the current container starts.
|
||||
flock 200
|
||||
echo "Apply database migrations..."
|
||||
sudo -HEu paperless python3 manage.py migrate
|
||||
) 200>/usr/src/paperless/data/migration_lock
|
||||
|
||||
@@ -38,13 +79,19 @@ initialize() {
|
||||
fi
|
||||
done
|
||||
|
||||
echo "creating directory /tmp/paperless"
|
||||
mkdir -p /tmp/paperless
|
||||
|
||||
chown -R paperless:paperless ../
|
||||
chown -R paperless:paperless /tmp/paperless
|
||||
|
||||
migrations
|
||||
|
||||
}
|
||||
|
||||
install_languages() {
|
||||
echo "Installing languages..."
|
||||
|
||||
local langs="$1"
|
||||
read -ra langs <<<"$langs"
|
||||
|
||||
@@ -79,16 +126,20 @@ install_languages() {
|
||||
done
|
||||
}
|
||||
|
||||
initialize
|
||||
echo "Paperless-ng docker container starting..."
|
||||
|
||||
# Install additional languages if specified
|
||||
if [[ ! -z "$PAPERLESS_OCR_LANGUAGES" ]]; then
|
||||
install_languages "$PAPERLESS_OCR_LANGUAGES"
|
||||
fi
|
||||
|
||||
initialize
|
||||
|
||||
if [[ "$1" != "/"* ]]; then
|
||||
echo Executing management command "$@"
|
||||
exec sudo -HEu paperless python3 manage.py "$@"
|
||||
else
|
||||
echo Executing "$@"
|
||||
exec "$@"
|
||||
fi
|
||||
|
||||
|
@@ -1,31 +0,0 @@
|
||||
version: "3.4"
|
||||
services:
|
||||
broker:
|
||||
image: redis:6.0
|
||||
restart: always
|
||||
|
||||
webserver:
|
||||
image: jonaswinkler/paperless-ng:0.9
|
||||
restart: always
|
||||
depends_on:
|
||||
- broker
|
||||
ports:
|
||||
- 8000:8000
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
volumes:
|
||||
- data:/usr/src/paperless/data
|
||||
- media:/usr/src/paperless/media
|
||||
- ./export:/usr/src/paperless/export
|
||||
- ./consume:/usr/src/paperless/consume
|
||||
env_file: docker-compose.env
|
||||
environment:
|
||||
PAPERLESS_REDIS: redis://broker:6379
|
||||
|
||||
|
||||
volumes:
|
||||
data:
|
||||
media:
|
@@ -1,44 +0,0 @@
|
||||
version: "3.4"
|
||||
services:
|
||||
broker:
|
||||
image: redis:6.0
|
||||
restart: always
|
||||
|
||||
db:
|
||||
image: postgres:13
|
||||
restart: always
|
||||
volumes:
|
||||
- pgdata:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_DB: paperless
|
||||
POSTGRES_USER: paperless
|
||||
POSTGRES_PASSWORD: paperless
|
||||
|
||||
webserver:
|
||||
image: jonaswinkler/paperless-ng:0.9
|
||||
restart: always
|
||||
depends_on:
|
||||
- db
|
||||
- broker
|
||||
ports:
|
||||
- 8000:8000
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
volumes:
|
||||
- data:/usr/src/paperless/data
|
||||
- media:/usr/src/paperless/media
|
||||
- ./export:/usr/src/paperless/export
|
||||
- ./consume:/usr/src/paperless/consume
|
||||
env_file: docker-compose.env
|
||||
environment:
|
||||
PAPERLESS_REDIS: redis://broker:6379
|
||||
PAPERLESS_DBHOST: db
|
||||
|
||||
|
||||
volumes:
|
||||
data:
|
||||
media:
|
||||
pgdata:
|
6
docker/install_management_commands.sh
Executable file
@@ -0,0 +1,6 @@
|
||||
for command in document_archiver document_exporter document_importer mail_fetcher document_create_classifier document_index document_renamer document_retagger document_thumbnails document_sanity_checker;
|
||||
do
|
||||
echo "installing $command..."
|
||||
sed "s/management_command/$command/g" management_script.sh > /usr/local/bin/$command
|
||||
chmod +x /usr/local/bin/$command
|
||||
done
|
@@ -1,64 +0,0 @@
|
||||
###############################################################################
|
||||
### Back end ###
|
||||
###############################################################################
|
||||
|
||||
FROM python:3.7-slim
|
||||
|
||||
WORKDIR /usr/src/paperless/
|
||||
|
||||
COPY requirements.txt ./
|
||||
|
||||
#Dependencies
|
||||
RUN apt-get update \
|
||||
&& apt-get -y --no-install-recommends install \
|
||||
build-essential \
|
||||
curl \
|
||||
ghostscript \
|
||||
gnupg \
|
||||
imagemagick \
|
||||
libatlas-base-dev \
|
||||
libmagic-dev \
|
||||
libpoppler-cpp-dev \
|
||||
libpq-dev \
|
||||
optipng \
|
||||
sudo \
|
||||
tesseract-ocr \
|
||||
tesseract-ocr-eng \
|
||||
tesseract-ocr-deu \
|
||||
tesseract-ocr-fra \
|
||||
tesseract-ocr-ita \
|
||||
tesseract-ocr-spa \
|
||||
tzdata \
|
||||
unpaper \
|
||||
&& pip3 install --upgrade supervisor setuptools \
|
||||
&& pip install --no-cache-dir -r requirements.txt \
|
||||
&& apt-get -y purge build-essential \
|
||||
&& apt-get -y autoremove --purge \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& mkdir /var/log/supervisord /var/run/supervisord
|
||||
|
||||
# copy scripts
|
||||
# this fixes issues with imagemagick and PDF
|
||||
COPY docker/imagemagick-policy.xml /etc/ImageMagick-6/policy.xml
|
||||
COPY docker/gunicorn.conf.py ./
|
||||
COPY docker/supervisord.conf /etc/supervisord.conf
|
||||
COPY docker/docker-entrypoint.sh /sbin/docker-entrypoint.sh
|
||||
|
||||
# copy app
|
||||
COPY src/ ./src/
|
||||
|
||||
# add users, setup scripts
|
||||
RUN addgroup --gid 1000 paperless \
|
||||
&& useradd --uid 1000 --gid paperless --home-dir /usr/src/paperless paperless \
|
||||
&& chown -R paperless:paperless . \
|
||||
&& chmod 755 /sbin/docker-entrypoint.sh
|
||||
|
||||
WORKDIR /usr/src/paperless/src/
|
||||
|
||||
RUN sudo -HEu paperless python3 manage.py collectstatic --clear --no-input
|
||||
|
||||
VOLUME ["/usr/src/paperless/data", "/usr/src/paperless/media", "/usr/src/paperless/consume", "/usr/src/paperless/export"]
|
||||
ENTRYPOINT ["/sbin/docker-entrypoint.sh"]
|
||||
CMD ["/usr/local/bin/supervisord", "-c", "/etc/supervisord.conf"]
|
||||
|
||||
LABEL maintainer="Jonas Winkler <dev@jpwinkler.de>"
|
@@ -1,31 +0,0 @@
|
||||
version: "3.4"
|
||||
services:
|
||||
broker:
|
||||
image: redis:6.0
|
||||
restart: always
|
||||
|
||||
webserver:
|
||||
build: .
|
||||
restart: always
|
||||
depends_on:
|
||||
- broker
|
||||
ports:
|
||||
- 8000:8000
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
volumes:
|
||||
- data:/usr/src/paperless/data
|
||||
- media:/usr/src/paperless/media
|
||||
- ./export:/usr/src/paperless/export
|
||||
- ./consume:/usr/src/paperless/consume
|
||||
env_file: docker-compose.env
|
||||
environment:
|
||||
PAPERLESS_REDIS: redis://broker:6379
|
||||
|
||||
|
||||
volumes:
|
||||
data:
|
||||
media:
|
@@ -1,44 +0,0 @@
|
||||
version: "3.4"
|
||||
services:
|
||||
broker:
|
||||
image: redis:6.0
|
||||
restart: always
|
||||
|
||||
db:
|
||||
image: postgres:13
|
||||
restart: always
|
||||
volumes:
|
||||
- pgdata:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_DB: paperless
|
||||
POSTGRES_USER: paperless
|
||||
POSTGRES_PASSWORD: paperless
|
||||
|
||||
webserver:
|
||||
build: .
|
||||
restart: always
|
||||
depends_on:
|
||||
- db
|
||||
- broker
|
||||
ports:
|
||||
- 8000:8000
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
volumes:
|
||||
- data:/usr/src/paperless/data
|
||||
- media:/usr/src/paperless/media
|
||||
- ./export:/usr/src/paperless/export
|
||||
- ./consume:/usr/src/paperless/consume
|
||||
env_file: docker-compose.env
|
||||
environment:
|
||||
PAPERLESS_REDIS: redis://broker:6379
|
||||
PAPERLESS_DBHOST: db
|
||||
|
||||
|
||||
volumes:
|
||||
data:
|
||||
media:
|
||||
pgdata:
|
15
docker/management_script.sh
Normal file
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
cd /usr/src/paperless/src/
|
||||
|
||||
if [[ $(id -u) == 0 ]] ;
|
||||
then
|
||||
sudo -HEu paperless python3 manage.py management_command "$@"
|
||||
elif [[ $(id -un) == "paperless" ]] ;
|
||||
then
|
||||
python3 manage.py management_command "$@"
|
||||
else
|
||||
echo "Unknown user."
|
||||
fi
|
@@ -8,7 +8,7 @@ loglevel=info ; log level; default info; others: debug,warn,trace
|
||||
user=root
|
||||
|
||||
[program:gunicorn]
|
||||
command=gunicorn -c /usr/src/paperless/gunicorn.conf.py -b 0.0.0.0:8000 paperless.wsgi
|
||||
command=gunicorn -c /usr/src/paperless/gunicorn.conf.py paperless.asgi:application
|
||||
user=paperless
|
||||
|
||||
stdout_logfile=/dev/stdout
|
||||
|
BIN
docs/_static/paperless-0-dashboard.png
vendored
Before Width: | Height: | Size: 52 KiB |
BIN
docs/_static/paperless-1-list-table.png
vendored
Before Width: | Height: | Size: 62 KiB |
BIN
docs/_static/paperless-10-mobile.png
vendored
Before Width: | Height: | Size: 56 KiB |
BIN
docs/_static/paperless-11-mail-filters.png
vendored
Before Width: | Height: | Size: 70 KiB |
BIN
docs/_static/paperless-2-list-smallcards.png
vendored
Before Width: | Height: | Size: 256 KiB |
BIN
docs/_static/paperless-3-list-largecards.png
vendored
Before Width: | Height: | Size: 224 KiB |
BIN
docs/_static/paperless-4-filter.png
vendored
Before Width: | Height: | Size: 101 KiB |
BIN
docs/_static/paperless-5-editing.png
vendored
Before Width: | Height: | Size: 196 KiB |
BIN
docs/_static/paperless-6-tags.png
vendored
Before Width: | Height: | Size: 50 KiB |
BIN
docs/_static/paperless-7-autocomplete.png
vendored
Before Width: | Height: | Size: 53 KiB |
BIN
docs/_static/paperless-8-search-results.png
vendored
Before Width: | Height: | Size: 214 KiB |
BIN
docs/_static/paperless-9-admin.png
vendored
Before Width: | Height: | Size: 50 KiB |
BIN
docs/_static/screenshots/correspondents.png
vendored
Normal file
After Width: | Height: | Size: 106 KiB |
BIN
docs/_static/screenshots/dashboard.png
vendored
Normal file
After Width: | Height: | Size: 167 KiB |
BIN
docs/_static/screenshots/documents-filter.png
vendored
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
docs/_static/screenshots/documents-largecards.png
vendored
Normal file
After Width: | Height: | Size: 306 KiB |
BIN
docs/_static/screenshots/documents-smallcards.png
vendored
Normal file
After Width: | Height: | Size: 410 KiB |
BIN
docs/_static/screenshots/documents-table.png
vendored
Normal file
After Width: | Height: | Size: 137 KiB |
BIN
docs/_static/screenshots/editing.png
vendored
Normal file
After Width: | Height: | Size: 293 KiB |
BIN
docs/_static/screenshots/logs.png
vendored
Normal file
After Width: | Height: | Size: 260 KiB |
BIN
docs/_static/screenshots/mail-rules-edited.png
vendored
Normal file
After Width: | Height: | Size: 96 KiB |
BIN
docs/_static/screenshots/mobile.png
vendored
Normal file
After Width: | Height: | Size: 158 KiB |
BIN
docs/_static/screenshots/new-tag.png
vendored
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
docs/_static/screenshots/search-preview.png
vendored
Normal file
After Width: | Height: | Size: 61 KiB |
BIN
docs/_static/screenshots/search-results.png
vendored
Normal file
After Width: | Height: | Size: 261 KiB |
@@ -20,6 +20,14 @@ Options available to any installation of paperless:
|
||||
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:
|
||||
|
||||
@@ -30,7 +38,7 @@ Options available to docker installations:
|
||||
Paperless uses 3 volumes:
|
||||
|
||||
* ``paperless_media``: This is where your documents are stored.
|
||||
* ``paperless_data``: This is where auxilliary data is stored. This
|
||||
* ``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.
|
||||
@@ -48,16 +56,16 @@ Options available to bare-metal and non-docker installations:
|
||||
Restoring
|
||||
=========
|
||||
|
||||
|
||||
|
||||
|
||||
.. _administration-updating:
|
||||
|
||||
Updating paperless
|
||||
Updating Paperless
|
||||
##################
|
||||
|
||||
Docker Route
|
||||
============
|
||||
|
||||
If a new release of paperless-ng is available, upgrading depends on how you
|
||||
installed paperless-ng in the first place. The releases are available at
|
||||
installed paperless-ng in the first place. The releases are available at the
|
||||
`release page <https://github.com/jonaswinkler/paperless-ng/releases>`_.
|
||||
|
||||
First of all, ensure that paperless is stopped.
|
||||
@@ -69,95 +77,162 @@ First of all, ensure that paperless is stopped.
|
||||
|
||||
After that, :ref:`make a backup <administration-backup>`.
|
||||
|
||||
A. If you used the docker-compose file, simply download the files of the new release,
|
||||
adjust the settings in the files (i.e., the path to your consumption directory),
|
||||
and replace your existing docker-compose files. Then start paperless as usual,
|
||||
which will pull the new image, and update your database, if necessary:
|
||||
A. If you pull the image from the docker hub, all you need to do is:
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
$ cd /path/to/paperless
|
||||
$ docker-compose pull
|
||||
$ docker-compose up
|
||||
|
||||
If you see everything working, you can start paperless-ng with "-d" to have it
|
||||
run in the background.
|
||||
The docker-compose files refer to the ``latest`` version, which is always the latest
|
||||
stable release.
|
||||
|
||||
B. If you built the image yourself, grab the new archive and replace your current
|
||||
paperless folder with the new contents.
|
||||
|
||||
After that, make the necessary adjustments to the docker-compose.yml (i.e.,
|
||||
adjust your consumption directory).
|
||||
|
||||
Build and start the new image with:
|
||||
B. If you built the image yourself, do the following:
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
$ cd /path/to/paperless
|
||||
$ git pull
|
||||
$ ./compile-frontend.sh
|
||||
$ docker-compose build
|
||||
$ docker-compose up
|
||||
|
||||
If you see everything working, you can start paperless-ng with "-d" to have it
|
||||
run in the background.
|
||||
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-ng with ``-d`` to have it run in the background.
|
||||
|
||||
.. hint::
|
||||
.. note::
|
||||
|
||||
You can usually keep your ``docker-compose.env`` file, since this file will
|
||||
never include mandantory configuration options. However, it is worth checking
|
||||
out the new version of this file, since it might have new recommendations
|
||||
on what to configure.
|
||||
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/jonaswinkler/paperless-ng/tree/master/docker/compose>`_
|
||||
or edit the ``docker-compose.yml`` file, find the line that says
|
||||
|
||||
.. code::
|
||||
|
||||
Updating paperless without docker
|
||||
=================================
|
||||
image: jonaswinkler/paperless-ng:0.9.x
|
||||
|
||||
and replace the version with ``latest``:
|
||||
|
||||
.. code::
|
||||
|
||||
image: jonaswinkler/paperless-ng:latest
|
||||
|
||||
Bare Metal Route
|
||||
================
|
||||
|
||||
After grabbing the new release and unpacking the contents, do the following:
|
||||
|
||||
1. Update python requirements. Paperless uses
|
||||
`Pipenv`_ for managing dependencies:
|
||||
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 --upgrade pipenv
|
||||
$ cd /path/to/paperless
|
||||
$ pipenv install
|
||||
$ pip install -r requirements.txt
|
||||
|
||||
This creates a new virtual environment (or uses your existing environment)
|
||||
and installs all dependencies into it.
|
||||
|
||||
2. Collect static files.
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
$ cd src
|
||||
$ pipenv run python3 manage.py collectstatic --clear
|
||||
|
||||
3. Migrate the database.
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
$ cd src
|
||||
$ pipenv run python3 manage.py migrate
|
||||
$ python3 manage.py migrate
|
||||
|
||||
This might not actually do anything. Not every new paperless version comes with new
|
||||
database migrations.
|
||||
|
||||
Ansible Route
|
||||
=============
|
||||
|
||||
Most of the update process is automated when using the ansible role.
|
||||
|
||||
1. Backup your defined role variables file outside the paperless source-tree:
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
$ cp ansible/vars.yml ~/vars.yml.old
|
||||
|
||||
2. Pull the release tag you want to update to:
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
$ git fetch --all
|
||||
$ git checkout ng-0.9.14
|
||||
|
||||
3. Update the role variable definitions ``ansible/vars.yml`` (where appropriate).
|
||||
|
||||
4. Run the ansible playbook you created created during :ref:`installation <setup-ansible>` again:
|
||||
|
||||
.. note::
|
||||
|
||||
When ansible detects that an update run is in progress, it backs up the entire ``paperlessng_directory`` to ``paperlessng_directory-TIMESTAMP``.
|
||||
Updates can be rolled back by simply moving the timestamped folder back to the original location.
|
||||
If the update succeeds and you want to continue using the new release, please don't forget to delete the backup folder.
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
$ ansible-playbook playbook.yml
|
||||
|
||||
|
||||
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 most recent database migrations for each versions:
|
||||
|
||||
+---------+-------------------------+
|
||||
| Version | Latest migration number |
|
||||
+---------+-------------------------+
|
||||
| 1.0.0 | 1011 |
|
||||
+---------+-------------------------+
|
||||
| 1.1.0 | 1011 |
|
||||
+---------+-------------------------+
|
||||
| 1.1.1 | 1012 |
|
||||
+---------+-------------------------+
|
||||
|
||||
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 invoce these commands either by
|
||||
tasks on your paperless instance. You can invoke these commands in the following way:
|
||||
|
||||
.. code:: bash
|
||||
With docker-compose, while paperless is running:
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
$ cd /path/to/paperless
|
||||
$ docker-compose run --rm webserver <command> <arguments>
|
||||
$ docker-compose exec webserver <command> <arguments>
|
||||
|
||||
or
|
||||
With docker, while paperless is running:
|
||||
|
||||
.. code:: bash
|
||||
.. code:: shell-session
|
||||
|
||||
$ docker exec -it <container-name> <command> <arguments>
|
||||
|
||||
Bare metal:
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
$ cd /path/to/paperless/src
|
||||
$ pipenv run python manage.py <command> <arguments>
|
||||
|
||||
depending on whether you use docker or not.
|
||||
$ python3 manage.py <command> <arguments>
|
||||
|
||||
All commands have built-in help, which can be accessed by executing them with
|
||||
the argument ``--help``.
|
||||
@@ -172,7 +247,12 @@ backup or migration to another DMS.
|
||||
|
||||
.. code::
|
||||
|
||||
document_exporter target
|
||||
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
|
||||
@@ -182,6 +262,24 @@ 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:
|
||||
|
||||
@@ -239,12 +337,12 @@ 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 behaviour and just use the first correspondent or type
|
||||
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 behaviour is to not
|
||||
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
|
||||
@@ -266,6 +364,7 @@ management command:
|
||||
|
||||
This command takes no arguments.
|
||||
|
||||
.. _`administration-index`:
|
||||
|
||||
Managing the document search index
|
||||
==================================
|
||||
@@ -311,6 +410,83 @@ the naming scheme.
|
||||
The command takes no arguments and processes all your documents at once.
|
||||
|
||||
|
||||
.. _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
|
||||
@@ -320,51 +496,32 @@ Documents can be stored in Paperless using GnuPG encryption.
|
||||
|
||||
.. danger::
|
||||
|
||||
Decryption is depreceated since paperless-ng 0.9 and doesn't really provide any
|
||||
Encryption is deprecated since paperless-ng 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.
|
||||
|
||||
.. code::
|
||||
|
||||
change_storage_type [--passphrase PASSPHRASE] {gpg,unencrypted} {gpg,unencrypted}
|
||||
|
||||
positional arguments:
|
||||
{gpg,unencrypted} The state you want to change your documents from
|
||||
{gpg,unencrypted} The state you want to change your documents to
|
||||
|
||||
optional arguments:
|
||||
--passphrase PASSPHRASE
|
||||
|
||||
Enabling encryption
|
||||
-------------------
|
||||
|
||||
Basic usage to enable encryption of your document store (**USE A MORE SECURE PASSPHRASE**):
|
||||
|
||||
(Note: If ``PAPERLESS_PASSPHRASE`` isn't set already, you need to specify it here)
|
||||
|
||||
.. code::
|
||||
|
||||
change_storage_type [--passphrase SECR3TP4SSPHRA$E] unencrypted gpg
|
||||
Enabling encryption is no longer supported.
|
||||
|
||||
|
||||
Disabling encryption
|
||||
--------------------
|
||||
|
||||
Basic usage to enable encryption of your document store:
|
||||
Basic usage to disable encryption of your document store:
|
||||
|
||||
(Note: Again, if ``PAPERLESS_PASSPHRASE`` isn't set already, you need to specify it here)
|
||||
(Note: If ``PAPERLESS_PASSPHRASE`` isn't set already, you need to specify it here)
|
||||
|
||||
.. code::
|
||||
|
||||
change_storage_type [--passphrase SECR3TP4SSPHRA$E] gpg unencrypted
|
||||
|
||||
|
||||
.. _Pipenv: https://pipenv.pypa.io/en/latest/
|
||||
decrypt_documents [--passphrase SECR3TP4SSPHRA$E]
|
||||
|
@@ -5,82 +5,7 @@ Advanced topics
|
||||
Paperless offers a couple features that automate certain tasks and make your life
|
||||
easier.
|
||||
|
||||
Guesswork
|
||||
#########
|
||||
|
||||
|
||||
Any document you put into the consumption directory will be consumed, but if
|
||||
you name the file right, it'll automatically set some values in the database
|
||||
for you. This is is the logic the consumer follows:
|
||||
|
||||
1. Try to find the correspondent, title, and tags in the file name following
|
||||
the pattern: ``Date - Correspondent - Title - tag,tag,tag.pdf``. Note that
|
||||
the format of the date is **rigidly defined** as ``YYYYMMDDHHMMSSZ`` or
|
||||
``YYYYMMDDZ``. The ``Z`` refers "Zulu time" AKA "UTC".
|
||||
The tags are optional, so the format ``Date - Correspondent - Title.pdf``
|
||||
works as well.
|
||||
2. If that doesn't work, we skip the date and try this pattern:
|
||||
``Correspondent - Title - tag,tag,tag.pdf``.
|
||||
3. If that doesn't work, we try to find the correspondent and title in the file
|
||||
name following the pattern: ``Correspondent - Title.pdf``.
|
||||
4. If that doesn't work, just assume that the name of the file is the title.
|
||||
|
||||
So given the above, the following examples would work as you'd expect:
|
||||
|
||||
* ``20150314000700Z - Some Company Name - Invoice 2016-01-01 - money,invoices.pdf``
|
||||
* ``20150314Z - Some Company Name - Invoice 2016-01-01 - money,invoices.pdf``
|
||||
* ``Some Company Name - Invoice 2016-01-01 - money,invoices.pdf``
|
||||
* ``Another Company - Letter of Reference.jpg``
|
||||
* ``Dad's Recipe for Pancakes.png``
|
||||
|
||||
These however wouldn't work:
|
||||
|
||||
* ``2015-03-14 00:07:00 UTC - Some Company Name, Invoice 2016-01-01, money, invoices.pdf``
|
||||
* ``2015-03-14 - Some Company Name, Invoice 2016-01-01, money, invoices.pdf``
|
||||
* ``Some Company Name, Invoice 2016-01-01, money, invoices.pdf``
|
||||
* ``Another Company- Letter of Reference.jpg``
|
||||
|
||||
Do I have to be so strict about naming?
|
||||
=======================================
|
||||
|
||||
Rather than using the strict document naming rules, one can also set the option
|
||||
``PAPERLESS_FILENAME_DATE_ORDER`` in ``paperless.conf`` to any date order
|
||||
that is accepted by dateparser_. Doing so will cause ``paperless`` to default
|
||||
to any date format that is found in the title, instead of a date pulled from
|
||||
the document's text, without requiring the strict formatting of the document
|
||||
filename as described above.
|
||||
|
||||
.. _dateparser: https://github.com/scrapinghub/dateparser/blob/v0.7.0/docs/usage.rst#settings
|
||||
|
||||
Transforming filenames for parsing
|
||||
==================================
|
||||
|
||||
Some devices can't produce filenames that can be parsed by the default
|
||||
parser. By configuring the option ``PAPERLESS_FILENAME_PARSE_TRANSFORMS`` in
|
||||
``paperless.conf`` one can add transformations that are applied to the filename
|
||||
before it's parsed.
|
||||
|
||||
The option contains a list of dictionaries of regular expressions (key:
|
||||
``pattern``) and replacements (key: ``repl``) in JSON format, which are
|
||||
applied in order by passing them to ``re.subn``. Transformation stops
|
||||
after the first match, so at most one transformation is applied. The general
|
||||
syntax is
|
||||
|
||||
.. code:: python
|
||||
|
||||
[{"pattern":"pattern1", "repl":"repl1"}, {"pattern":"pattern2", "repl":"repl2"}, ..., {"pattern":"patternN", "repl":"replN"}]
|
||||
|
||||
The example below is for a Brother ADS-2400N, a scanner that allows
|
||||
different names to different hardware buttons (useful for handling
|
||||
multiple entities in one instance), but insists on adding ``_<count>``
|
||||
to the filename.
|
||||
|
||||
.. code:: python
|
||||
|
||||
# Brother profile configuration, support "Name_Date_Count" (the default
|
||||
# setting) and "Name_Count" (use "Name" as tag and "Count" as title).
|
||||
PAPERLESS_FILENAME_PARSE_TRANSFORMS=[{"pattern":"^([a-z]+)_(\\d{8})_(\\d{6})_([0-9]+)\\.", "repl":"\\2\\3Z - \\4 - \\1."}, {"pattern":"^([a-z]+)_([0-9]+)\\.", "repl":" - \\2 - \\1."}]
|
||||
|
||||
.. _advanced-matching:
|
||||
|
||||
Matching tags, correspondents and document types
|
||||
################################################
|
||||
@@ -143,7 +68,9 @@ 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.
|
||||
|
||||
There are a couple caveats you need to keep in mind when using this feature:
|
||||
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
|
||||
@@ -163,6 +90,11 @@ There are a couple caveats you need to keep in mind when using this feature:
|
||||
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 or type. 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
|
||||
####################################
|
||||
@@ -219,6 +151,7 @@ the consumption process will begin with the newly modified file.
|
||||
|
||||
.. _pdf2pdfocr.py: https://github.com/LeoFCardoso/pdf2pdfocr
|
||||
|
||||
.. _advanced-post_consume_script:
|
||||
|
||||
Post-consumption script
|
||||
=======================
|
||||
@@ -250,11 +183,11 @@ By default, paperless stores your documents in the media directory and renames t
|
||||
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 adjustng the
|
||||
``PAPERLESS_FILENAME_FORMAT`` settings variable.
|
||||
you wish to name your files differently, you can do that by adjusting the
|
||||
``PAPERLESS_FILENAME_FORMAT`` configuration option.
|
||||
|
||||
This variable allows you to configure the filename (folders are allowed!) using
|
||||
placeholders. For example, setting
|
||||
This variable allows you to configure the filename (folders are allowed) using
|
||||
placeholders. For example, configuring this to
|
||||
|
||||
.. code:: bash
|
||||
|
||||
@@ -265,17 +198,16 @@ will create a directory structure as follows:
|
||||
.. code::
|
||||
|
||||
2019/
|
||||
my_bank/
|
||||
statement-january-0000001.pdf
|
||||
statement-february-0000002.pdf
|
||||
My bank/
|
||||
Statement January.pdf
|
||||
Statement February.pdf
|
||||
2020/
|
||||
my_bank/
|
||||
statement-january-0000003.pdf
|
||||
shoe_store/
|
||||
my_new_shoes-0000004.pdf
|
||||
|
||||
Paperless appends the unique identifier of each document to the filename. This
|
||||
avoides filename clashes.
|
||||
My bank/
|
||||
Statement January.pdf
|
||||
Letter.pdf
|
||||
Letter_01.pdf
|
||||
Shoe store/
|
||||
My new shoes.pdf
|
||||
|
||||
.. danger::
|
||||
|
||||
@@ -285,7 +217,10 @@ avoides filename clashes.
|
||||
|
||||
Paperless provides the following placeholders withing 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 and time the document was created.
|
||||
* ``{created_year}``: Year created only.
|
||||
@@ -295,10 +230,15 @@ Paperless provides the following placeholders withing filenames:
|
||||
* ``{added_year}``: Year added only.
|
||||
* ``{added_month}``: Month added only (number 1-12).
|
||||
* ``{added_day}``: Day added only (number 1-31).
|
||||
* ``{tags}``: I don't know how this works. Look at the source.
|
||||
|
||||
Paperless will convert all values for the placeholders into values which are safe
|
||||
for use in filenames.
|
||||
|
||||
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::
|
||||
|
||||
|
160
docs/api.rst
@@ -13,23 +13,55 @@ 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/documents/``: Full CRUD support, except POSTing new documents. See below.
|
||||
* ``/api/logs/``: Read-Only.
|
||||
* ``/api/tags/``: Full CRUD support.
|
||||
|
||||
All of these endpoints except for the logging endpoint
|
||||
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 at which this document was created.
|
||||
* ``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 original document.
|
||||
* ``/api/documents/<pk>/thumb/``: Download the PNG thumbnail of a document.
|
||||
* ``/api/documents/<pk>/preview/``: Display the original document inline,
|
||||
* ``/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 archied document is available,
|
||||
supply the query parameter ``original=true``.
|
||||
|
||||
.. hint::
|
||||
|
||||
@@ -38,6 +70,80 @@ individual documents:
|
||||
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
|
||||
#######################
|
||||
|
||||
@@ -65,8 +171,9 @@ Result list object returned by the endpoint:
|
||||
"count": 1,
|
||||
"page": 1,
|
||||
"page_count": 1,
|
||||
"corrected_query": "",
|
||||
"results": [
|
||||
|
||||
|
||||
]
|
||||
}
|
||||
|
||||
@@ -75,6 +182,8 @@ Result list object returned by the endpoint:
|
||||
the page you requested, if you requested a page that is behind
|
||||
the last page. In that case, the last page is returned.
|
||||
* ``page_count``: The total number of pages.
|
||||
* ``corrected_query``: Corrected version of the query string. Can be null.
|
||||
If not null, can be used verbatim to start a new query.
|
||||
* ``results``: A list of result objects on the current page.
|
||||
|
||||
Result object:
|
||||
@@ -84,16 +193,17 @@ Result object:
|
||||
{
|
||||
"id": 1,
|
||||
"highlights": [
|
||||
|
||||
|
||||
],
|
||||
"score": 6.34234,
|
||||
"rank": 23,
|
||||
"document": {
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
* ``id``: the primary key of the found document
|
||||
* ``highlights``: an object containing parseable highlights for the result.
|
||||
* ``highlights``: an object containing parsable highlights for the result.
|
||||
See below.
|
||||
* ``score``: The score assigned to the document. A higher score indicates a
|
||||
better match with the query. Search results are sorted descending by score.
|
||||
@@ -109,21 +219,18 @@ Each fragment contains a list of strings, and some of them are marked as a highl
|
||||
|
||||
.. code:: json
|
||||
|
||||
"highlights": [
|
||||
[
|
||||
[
|
||||
{"text": "This is a sample text with a "},
|
||||
{"text": "highlighted", "term": 0},
|
||||
{"text": " word."}
|
||||
{"text": "This is a sample text with a ", "highlight": false},
|
||||
{"text": "highlighted", "highlight": true},
|
||||
{"text": " word.", "highlight": false}
|
||||
],
|
||||
[
|
||||
{"text": "Another", "term": 1},
|
||||
{"text": " fragment with a highlight."}
|
||||
{"text": "Another", "highlight": true},
|
||||
{"text": " fragment with a highlight.", "highlight": false}
|
||||
]
|
||||
]
|
||||
|
||||
When ``term`` is present within a string, the word within ``text`` should be highlighted.
|
||||
The term index groups multiple matches together and words with the same index
|
||||
should get identical highlighting.
|
||||
A client may use this example to produce the following output:
|
||||
|
||||
... This is a sample text with a **highlighted** word. ... **Another** fragment with a highlight. ...
|
||||
@@ -163,8 +270,17 @@ The API provides a special endpoint for file uploads:
|
||||
|
||||
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 the consumption folder, where the consumer will
|
||||
detect the document and process it as any other document.
|
||||
then used to store the document in a temporary directory, and the consumer will
|
||||
be instructed to consume the document from there.
|
||||
|
||||
The endpoint will immediately return "OK." if the document was stored in the
|
||||
consumption directory.
|
||||
The endpoint supports the following optional form fields:
|
||||
|
||||
* ``title``: Specify a title that the consumer should use for the document.
|
||||
* ``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.
|
||||
|
@@ -5,6 +5,573 @@
|
||||
Changelog
|
||||
*********
|
||||
|
||||
paperless-ng 1.2.0
|
||||
##################
|
||||
|
||||
* Changes to the OCRmyPDF integration
|
||||
|
||||
* Added support for deskewing and automatic rotation of incorrectly rotated pages. This is enabled by default, see :ref:`configuration-ocr`.
|
||||
* Better support for encrypted files.
|
||||
* Better support for various other PDF files: Paperless will now attempt to force OCR with safe options when OCR fails with the configured options.
|
||||
* Added an explicit option to skip cleaning with ``unpaper``.
|
||||
|
||||
* Download multiple selected documents as a zip archive.
|
||||
|
||||
* The document list now remembers the current page.
|
||||
|
||||
* Improved responsiveness when switching between saved views and the document list.
|
||||
|
||||
* Increased the default wait time when observing files in the consumption folder
|
||||
with polling from 1 to 5 seconds. This will decrease the likelihood of paperless
|
||||
consuming partially written files.
|
||||
|
||||
* Fixed a crash of the document archiver management command when trying to process documents with unknown mime types.
|
||||
|
||||
* Paperless no longer depends on ``libpoppler-cpp-dev``.
|
||||
|
||||
.. note::
|
||||
|
||||
Some packages that paperless depends on are slowly dropping Python 3.6
|
||||
support one after another, including the web server. Supporting Python
|
||||
3.6 means that I cannot update these packages anymore.
|
||||
|
||||
At some point, paperless will drop Python 3.6 support. If using a bare
|
||||
metal installation and you're still on Python 3.6, upgrade to 3.7 or newer.
|
||||
|
||||
If using docker, this does not affect you.
|
||||
|
||||
paperless-ng 1.1.4
|
||||
##################
|
||||
|
||||
* Added English (GB) locale.
|
||||
|
||||
* Added ISO-8601 date display option.
|
||||
|
||||
paperless-ng 1.1.3
|
||||
##################
|
||||
|
||||
* Added a docker-specific configuration option to adjust the number of
|
||||
worker processes of the web server. See :ref:`configuration-docker`.
|
||||
|
||||
* Some more memory usage optimizations.
|
||||
|
||||
* Don't show inbox statistics if no inbox tag is defined.
|
||||
|
||||
paperless-ng 1.1.2
|
||||
##################
|
||||
|
||||
* Always show top left corner of thumbnails, even for extra wide documents.
|
||||
|
||||
* Added a management command for executing the sanity checker directly.
|
||||
See :ref:`utilities-sanity-checker`.
|
||||
|
||||
* The weekly sanity check now reports messages in the log files.
|
||||
|
||||
* Fixed an issue with the metadata tab not reporting anything in case of missing files.
|
||||
|
||||
* Reverted a change from 1.1.0 that caused huge memory usage due to redis caching.
|
||||
|
||||
* Some memory usage optimizations.
|
||||
|
||||
paperless-ng 1.1.1
|
||||
##################
|
||||
|
||||
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 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 filenames of two or more documents are the same, except for the file extension.
|
||||
* 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 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 used.
|
||||
|
||||
* 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 permission issues. See :ref:`utilities-management-commands`.
|
||||
|
||||
paperless-ng 1.1.0
|
||||
##################
|
||||
|
||||
* Document processing status
|
||||
|
||||
* Paperless now shows the status of processing documents on the dashboard in real time.
|
||||
* Status notifications when
|
||||
|
||||
* New documents are detected in the consumption folder, in mails, uploaded on the front end,
|
||||
or added with one of the mobile apps.
|
||||
* Documents are successfully added to paperless.
|
||||
* Document consumption failed (with error messages)
|
||||
|
||||
* Configuration options to enable/disable individual notifications.
|
||||
|
||||
* Live updates to document lists and saved views when new documents are added.
|
||||
|
||||
.. hint::
|
||||
|
||||
For status notifications and live updates to work, paperless now requires an `ASGI <https://asgi.readthedocs.io/en/latest/>`_-enabled
|
||||
web server. The docker images uses ``gunicorn`` and an ASGI-enabled worker called `uvicorn <http://www.uvicorn.org/>`_,
|
||||
and there is no need to configure anything.
|
||||
|
||||
For bare metal installations, changes are required for the notifications to work. Adapt the service ``paperless-webserver.service``
|
||||
to use the supplied ``gunicorn.conf.py`` configuration file and adapt the reference to the ASGI application as follows:
|
||||
|
||||
.. code::
|
||||
|
||||
ExecStart=/opt/paperless/.local/bin/gunicorn -c /opt/paperless/gunicorn.conf.py paperless.asgi:application
|
||||
|
||||
Paperless will continue to work with WSGI, but you will not get any status notifications.
|
||||
|
||||
Apache ``mod_wsgi`` users, see :ref:`this note <faq-mod_wsgi>`.
|
||||
|
||||
* Paperless now offers suggestions for tags, correspondents and types on the document detail page.
|
||||
|
||||
* Added an interactive easy install script that automatically downloads, configures and starts paperless with docker.
|
||||
|
||||
* Official support for Python 3.9.
|
||||
|
||||
* Other changes and fixes
|
||||
|
||||
* Adjusted the default parallelization settings to run more than one task in parallel on systems with 4 or less cores.
|
||||
This addresses issues with paperless not consuming any new files when other tasks are running.
|
||||
|
||||
* Fixed a rare race condition that would cause paperless to process incompletely written files when using the upload on the dashboard.
|
||||
|
||||
* The document classifier no longer issues warnings and errors when auto matching is not used at all.
|
||||
|
||||
* 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.
|
||||
|
||||
* 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
|
||||
``PAPERLESS_LOGROTATE_MAX_BACKUPS``.
|
||||
|
||||
paperless-ng 1.0.0
|
||||
##################
|
||||
|
||||
Nothing special about this release, but since there are relatively few bug reports coming in, I think that this is reasonably stable.
|
||||
|
||||
* Document export
|
||||
|
||||
* The document exporter has been rewritten to support updating an already existing export in place.
|
||||
This enables incremental backups with ``rsync``.
|
||||
* The document exporter supports naming exported files according to ``PAPERLESS_FILENAME_FORMAT``.
|
||||
* The document exporter locks the media directory and the database during execution to ensure that
|
||||
the resulting export is consistent.
|
||||
* See the :ref:`updated documentation <utilities-exporter>` for more details.
|
||||
|
||||
* Other changes and additions
|
||||
|
||||
* Added a language selector to the settings.
|
||||
* Added date format options to the settings.
|
||||
* 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.
|
||||
|
||||
|
||||
paperless-ng 0.9.14
|
||||
###################
|
||||
|
||||
Starting with this version, releases are getting built automatically. This release also comes with changes on how to install and
|
||||
update paperless.
|
||||
|
||||
* Paperless now uses GitHub Actions to make releases and build docker images.
|
||||
|
||||
* Docker images are available for amd64, armhf, and aarch64.
|
||||
* When you pull an image from Docker Hub, Docker will automatically select the correct image for you.
|
||||
|
||||
* Changes to docker installations and updates
|
||||
|
||||
* The ``-dockerfiles.tar.xz`` release archive is gone. Instead, simply grab the docker files from ``/docker/compose`` in the repository
|
||||
if you wish to install paperless by pulling from the hub.
|
||||
* The docker compose files in ``/docker/compose`` were changed to always use the ``latest`` version automatically. In order to do further
|
||||
updates, simply do a ``docker-compose pull``. The documentation has been updated.
|
||||
* The docker compose files were changed to restart paperless on system boot only if it was running before shutdown.
|
||||
* Documentation of the docker-compose files about what they do.
|
||||
|
||||
* Changes to bare metal installations and updates
|
||||
|
||||
* The release archive is built exactly like before. However, the release now comes with already compiled translation messages and
|
||||
collected static files. Therefore, the update steps ``compilemessages`` and ``collectstatic`` are now obsolete.
|
||||
|
||||
* Other changes
|
||||
|
||||
* A new configuration option ``PAPERLESS_IGNORE_DATES`` was added by `jayme-github`_. This can be used to instruct paperless to ignore
|
||||
certain dates (such as your date of birth) when guessing the date from the document content. This was actually introduced in 0.9.12,
|
||||
I just forgot to mention it in the changelog.
|
||||
* The filter drop downs now display selected entries on top of all other entries.
|
||||
* The PostgreSQL client now supports setting an explicit ``sslmode`` to force encryption of the connection to PostgreSQL.
|
||||
* The docker images now come with ``jbig2enc``, which is a lossless image encoder for PDF documents and decreases the size of certain
|
||||
PDF/A documents.
|
||||
* When using any of the manual matching algorithms, paperless now logs messages about when and why these matching algorithms matched.
|
||||
* The default settings for parallelization in paperless were adjusted to always leave one CPU core free.
|
||||
* Added an option to the frontend to choose which method to use for displaying PDF documents.
|
||||
|
||||
* Fixes
|
||||
|
||||
* An issue with the tika parser not picking up files from the consumption directory was fixed.
|
||||
* A couple changes to the dark mode and fixes to several other layout issues.
|
||||
* An issue with the drop downs for correspondents, tags and types not properly supporting filtering with special characters was fixed.
|
||||
* 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 the issue.
|
||||
* An issue with the consumer crashing when invalid regular expression were used was fixed.
|
||||
|
||||
paperless-ng 0.9.13
|
||||
###################
|
||||
|
||||
* Fixed an issue with Paperless not starting due to the new Tika integration when ``USERMAP_UID`` and ``USERMAP_GID`` was used
|
||||
in the ``docker-compose.env`` file.
|
||||
|
||||
paperless-ng 0.9.12
|
||||
###################
|
||||
|
||||
* Paperless localization
|
||||
|
||||
* Thanks to the combined efforts of many users, Paperless is now available in English, Dutch, French and German.
|
||||
|
||||
* Thanks to `Jo Vandeginste`_, Paperless has optional support for Office documents such as .docx, .doc, .odt and more.
|
||||
|
||||
* See the :ref:`configuration<configuration-tika>` on how to enable this feature. This feature requires two additional services
|
||||
(one for parsing Office documents and metadata extraction and another for converting Office documents to PDF), and is therefore
|
||||
not enabled on default installations.
|
||||
* As with all other documents, paperless converts Office documents to PDF and stores both the original as well as the archived PDF.
|
||||
|
||||
* Dark mode
|
||||
|
||||
* Thanks to `Michael Shamoon`_, paperless now has a dark mode. Configuration is available in the settings.
|
||||
|
||||
* Other changes and additions
|
||||
|
||||
* The PDF viewer now uses a local copy of some dependencies instead of fetching them from the internet. Thanks to `slorenz`_.
|
||||
* Revamped search bar styling thanks to `Michael Shamoon`_.
|
||||
* Sorting in the document list by clicking on table headers.
|
||||
* A button was added to the document detail page that assigns a 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.
|
||||
* 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 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 filename filters
|
||||
with wildcards.
|
||||
* Support for remote user authentication thanks to `Michael 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 correctly restores the default filters on saved views. Thanks to `Michael Shamoon`_
|
||||
|
||||
* Fixes
|
||||
|
||||
* 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.
|
||||
* The post consumption script is executed later in the consumption process. Before the change, an ID was passed to the script referring to
|
||||
a document that did not yet exist in the database.
|
||||
|
||||
paperless-ng 0.9.11
|
||||
###################
|
||||
|
||||
* Fixed an issue with the docker image not starting at all due to a configuration change of the web server.
|
||||
|
||||
|
||||
paperless-ng 0.9.10
|
||||
###################
|
||||
|
||||
* Bulk editing
|
||||
|
||||
* Thanks to `Michael Shamoon`_, we've got a new interface for the bulk editor.
|
||||
* There are some configuration options in the settings to alter the behavior.
|
||||
|
||||
* Other changes and additions
|
||||
|
||||
* Thanks to `zjean`_, paperless now 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 or tags assigned.
|
||||
* Tags, types and correspondents are now sorted case insensitive.
|
||||
* Lots of preparation work for localization support.
|
||||
|
||||
* Fixes
|
||||
|
||||
* Added missing dependencies for Raspberry Pi builds.
|
||||
* Fixed an issue with plain text file consumption: Thumbnail generation failed due to missing fonts.
|
||||
* An issue with the search index reporting missing documents after bulk deletes was fixed.
|
||||
* Issue with the tag selector not clearing input correctly.
|
||||
* The consumer used to stop working when encountering an incomplete classifier model file.
|
||||
|
||||
.. note::
|
||||
|
||||
The bulk delete operations did not update the search index. Therefore, documents that you deleted remained in the index and
|
||||
caused the search to return messages about missing documents when searching. Further bulk operations will properly update
|
||||
the index.
|
||||
|
||||
However, this change is not retroactive: If you used the delete method of the bulk editor, you need to reindex your search index
|
||||
by :ref:`running the management command document_index with the argument reindex <administration-index>`.
|
||||
|
||||
paperless-ng 0.9.9
|
||||
##################
|
||||
|
||||
Christmas release!
|
||||
|
||||
* Bulk editing
|
||||
|
||||
* Paperless now supports bulk editing.
|
||||
* 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.
|
||||
|
||||
* Searching
|
||||
|
||||
* 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.
|
||||
* New select interface for tags, types and correspondents allows filtering. This also improves tag selection. Thanks again to `Michael Shamoon`_!
|
||||
* Page navigation controls for the document viewer, thanks to `Michael Shamoon`_.
|
||||
* Layout changes to the small cards document list.
|
||||
* The dashboard now displays the username (or full name if specified in the admin) on the dashboard.
|
||||
|
||||
* Fixes
|
||||
|
||||
* An error that caused the document importer to crash was fixed.
|
||||
* An issue with changes not being possible when ``PAPERLESS_COOKIE_PREFIX`` is used was fixed.
|
||||
* The date selection filters now allow manual entry of dates.
|
||||
|
||||
* Feature Removal
|
||||
|
||||
* Most of the guesswork features have been removed. Paperless no longer tries to extract correspondents and tags from file names.
|
||||
|
||||
paperless-ng 0.9.8
|
||||
##################
|
||||
|
||||
This release addresses two severe issues with the previous release.
|
||||
|
||||
* The delete buttons for document types, correspondents and tags were not working.
|
||||
* The document section in the admin was causing internal server errors (500).
|
||||
|
||||
|
||||
paperless-ng 0.9.7
|
||||
##################
|
||||
|
||||
|
||||
* Front end
|
||||
|
||||
* Thanks to the hard work of `Michael Shamoon`_, paperless now comes with a much more streamlined UI for
|
||||
filtering documents.
|
||||
|
||||
* `Michael Shamoon`_ replaced the document preview with another component. This should fix compatibility with Safari browsers.
|
||||
|
||||
* Added buttons to the management pages to quickly show all documents with one specific tag, correspondent, or title.
|
||||
|
||||
* Paperless now stores your saved views on the server and associates them with your user account.
|
||||
This means that you can access your views on multiple devices and have separate views for different users.
|
||||
You will have to recreate your views.
|
||||
|
||||
* The GitHub and documentation links now open in new tabs/windows. Thanks to `rYR79435`_.
|
||||
|
||||
* Paperless now generates default saved view names when saving views with certain filter rules.
|
||||
|
||||
* Added a small version indicator to the front end.
|
||||
|
||||
* Other additions and changes
|
||||
|
||||
* The new filename format field ``{tag_list}`` inserts a list of tags into the filename, separated by comma.
|
||||
* The ``document_retagger`` no longer removes inbox tags or tags without matching rules.
|
||||
* The new configuration option ``PAPERLESS_COOKIE_PREFIX`` allows you to run multiple instances of paperless on different ports.
|
||||
This option enables you to be logged in into multiple instances by specifying different cookie names for each instance.
|
||||
|
||||
* Fixes
|
||||
|
||||
* Sometimes paperless would assign dates in the future to newly consumed documents.
|
||||
* The filename format fields ``{created_month}`` and ``{created_day}`` now use a leading zero for single digit values.
|
||||
* The filename format field ``{tags}`` can no longer be used without arguments.
|
||||
* Paperless was not able to consume many images (especially images from mobile scanners) due to missing DPI information.
|
||||
Paperless now assumes A4 paper size for PDF generation if no DPI information is present.
|
||||
* Documents with empty titles could not be opened from the table view due to the link being empty.
|
||||
* Fixed an issue with filenames containing special characters such as ``:`` not being accepted for upload.
|
||||
* Fixed issues with thumbnail generation for plain text files.
|
||||
|
||||
|
||||
paperless-ng 0.9.6
|
||||
##################
|
||||
|
||||
This release focusses primarily on many small issues with the UI.
|
||||
|
||||
* Front end
|
||||
|
||||
* 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 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 a certain tag.
|
||||
* The file upload box now shows upload progress.
|
||||
* The document edit page was reorganized.
|
||||
* The document edit page shows various information about a document.
|
||||
* An issue with the height of the preview was fixed.
|
||||
* Table issues with too long document titles fixed.
|
||||
|
||||
* API
|
||||
|
||||
* The API now serves file names with documents.
|
||||
* The API now serves various metadata about documents.
|
||||
* API documentation updated.
|
||||
|
||||
* Other
|
||||
|
||||
* Fixed an issue with the docker image when a non-standard PostgreSQL port was used.
|
||||
* The docker image was trying check for installed languages before actually installing them.
|
||||
* ``FILENAME_FORMAT`` placeholder for document types.
|
||||
* The filename formatter is now less restrictive with file names and tries to
|
||||
conserve the original correspondents, types and titles as much as possible.
|
||||
* The filename formatter does not include the document ID in filenames anymore. It will
|
||||
rather append ``_01``, ``_02``, etc when it detects duplicate filenames.
|
||||
|
||||
.. 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
|
||||
##################
|
||||
|
||||
This release concludes the big changes I wanted to get rolled into paperless. The next releases before 1.0 will
|
||||
focus on fixing issues, primarily.
|
||||
|
||||
* OCR
|
||||
|
||||
* Paperless now uses `OCRmyPDF <https://github.com/jbarlow83/OCRmyPDF>`_ to perform OCR on documents.
|
||||
It still uses tesseract under the hood, but the PDF parser of Paperless has changed considerably and
|
||||
will behave different for some douments.
|
||||
* OCRmyPDF creates archived PDF/A documents with embedded text that can be selected in the front end.
|
||||
* Paperless stores archived versions of documents alongside with the originals. The originals can be
|
||||
accessed on the document edit page. If available, a dropdown menu will appear next to the download button.
|
||||
* Many of the configuration options regarding OCR have changed. See :ref:`configuration-ocr` for details.
|
||||
* Paperless no longer guesses the language of your documents. It always uses the language that you
|
||||
specified with ``PAPERLESS_OCR_LANGUAGE``. Be sure to set this to the language the majority of your
|
||||
documents are in. Multiple languages can be specified, but that requires more CPU time.
|
||||
* The management command :ref:`document_archiver <utilities-archiver>` can be used to create archived versions for already
|
||||
existing documents.
|
||||
|
||||
* Tags from consumption folder.
|
||||
|
||||
* Thanks to `jayme-github`_, paperless now consumes files from sub folders in the consumption folder and is able to assign tags
|
||||
based on the sub folders a document was found in. This can be configured with ``PAPERLESS_CONSUMER_RECURSIVE`` and
|
||||
``PAPERLESS_CONSUMER_SUBDIRS_AS_TAGS``.
|
||||
|
||||
* API
|
||||
|
||||
* The API now offers token authentication.
|
||||
* The endpoint for uploading documents now supports specifying custom titles, correspondents, tags and types.
|
||||
This can be used by clients to override the default behavior of paperless. See :ref:`api-file_uploads`.
|
||||
* The document endpoint of API now serves documents in this form:
|
||||
|
||||
* correspondents, document types and tags are referenced by their ID in the fields ``correspondent``, ``document_type`` and ``tags``. The ``*_id`` versions are gone. These fields are read/write.
|
||||
* paperless does not serve nested tags, correspondents or types anymore.
|
||||
|
||||
* Front end
|
||||
|
||||
* Paperless does some basic caching of correspondents, tags and types and will only request them from the server when necessary or when entirely reloading the page.
|
||||
* Document list fetching is about 10%-30% faster now, especially when lots of tags/correspondents are present.
|
||||
* Some minor improvements to the front end, such as document count in the document list, better highlighting of the current page, and improvements to the filter behavior.
|
||||
|
||||
* Fixes:
|
||||
|
||||
* A bug with the generation of filenames for files with unsupported types caused the exporter and
|
||||
document saving to crash.
|
||||
* Mail handling no longer exits entirely when encountering errors. It will skip the account/rule/message on which the error occured.
|
||||
* Assigning correspondents from mail sender names failed for very long names. Paperless no longer assigns correspondents in these cases.
|
||||
|
||||
paperless-ng 0.9.4
|
||||
##################
|
||||
|
||||
* Searching:
|
||||
|
||||
* Paperless now supports searching by tags, types and dates and correspondents. In order to have this applied to your
|
||||
existing documents, you need to perform a ``document_index reindex`` management command
|
||||
(see :ref:`administration-index`)
|
||||
that adds the data to the search index. You only 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 miss-typed queries.
|
||||
* The documentation contains :ref:`information about the query syntax <basic-searching>`.
|
||||
|
||||
* Front end:
|
||||
|
||||
* Clickable tags, correspondents and types allow quick filtering for related documents.
|
||||
* Saved views are now editable.
|
||||
* Preview documents directly in the browser.
|
||||
* Navigation from the dashboard to saved views.
|
||||
|
||||
* Fixes:
|
||||
|
||||
* A severe error when trying to use post consume scripts.
|
||||
* An error in the consumer that cause invalid messages of missing files to show up in the log.
|
||||
|
||||
* The documentation now contains information about bare metal installs and a section about
|
||||
how to setup the development environment.
|
||||
|
||||
paperless-ng 0.9.3
|
||||
##################
|
||||
|
||||
* Setting ``PAPERLESS_AUTO_LOGIN_USERNAME`` replaces ``PAPERLESS_DISABLE_LOGIN``.
|
||||
You have to specify your username.
|
||||
* Added a simple sanity checker that checks your documents for missing or orphaned files,
|
||||
files with wrong checksums, inaccessible files, and documents with empty content.
|
||||
* It is no longer possible to encrypt your documents. For the time being, paperless will
|
||||
continue to operate with already encrypted documents.
|
||||
* Fixes:
|
||||
|
||||
* Paperless now uses inotify again, since the watchdog was causing issues which I was not
|
||||
aware of.
|
||||
* Issue with the automatic classifier not working with only one tag.
|
||||
* A couple issues with the search index being opened to eagerly.
|
||||
|
||||
* Added lots of tests for various parts of the application.
|
||||
|
||||
paperless-ng 0.9.2
|
||||
##################
|
||||
|
||||
* Major changes to the front end (colors, logo, shadows, layout of the cards,
|
||||
better mobile support)
|
||||
|
||||
* Paperless now uses mime types and libmagic detection to determine
|
||||
if a file type is supported and which parser to use. Removes all
|
||||
file type checks that where present in MANY different places in
|
||||
paperless.
|
||||
|
||||
* Mail consumer now correctly consumes documents even when their
|
||||
content type was not set correctly. (i.e. PDF documents with
|
||||
content type ``application/octet-stream``)
|
||||
|
||||
* Basic sorting of mail rules added
|
||||
|
||||
* Much better admin for mail rule editing.
|
||||
|
||||
* Docker entrypoint script awaits the database server if it is
|
||||
configured.
|
||||
|
||||
* Disabled editing of logs.
|
||||
|
||||
* New setting ``PAPERLESS_OCR_PAGES`` limits the tesseract parser
|
||||
to the first n pages of scanned documents.
|
||||
|
||||
* Fixed a bug where tasks with too long task names would not show
|
||||
up in the admin.
|
||||
|
||||
paperless-ng 0.9.1
|
||||
##################
|
||||
|
||||
* Moved documentation of the settings to the actual documentation.
|
||||
* Updated release script to force the user to choose between SQLite
|
||||
and PostgreSQL. This avoids confusion when upgrading from paperless.
|
||||
|
||||
|
||||
paperless-ng 0.9.0
|
||||
##################
|
||||
|
||||
@@ -14,7 +581,7 @@ paperless-ng 0.9.0
|
||||
* **Added:** New frontend. Features:
|
||||
|
||||
* Single page application: It's much more responsive than the django admin pages.
|
||||
* Dashboard. Shows recently scanned documents, or todos, or other documents
|
||||
* Dashboard. Shows recently scanned documents, or todo notes, or other documents
|
||||
at wish. Allows uploading of documents. Shows basic statistics.
|
||||
* Better document list with multiple display options.
|
||||
* Full text search with result highlighting, auto completion and scoring based
|
||||
@@ -64,9 +631,8 @@ paperless-ng 0.9.0
|
||||
|
||||
* **Modified [breaking]:** PostgreSQL:
|
||||
|
||||
* If ``PAPERLESS_DBHOST`` is specified in the settings, paperless uses postgresql instead of sqlite.
|
||||
* If ``PAPERLESS_DBHOST`` is specified in the settings, paperless uses PostgreSQL instead of SQLite.
|
||||
Username, database and password all default to ``paperless`` if not specified.
|
||||
* **docker-compose.yml uses PostgreSQL by default.**
|
||||
|
||||
* **Modified [breaking]:** document_retagger management command rework. See
|
||||
:ref:`utilities-retagger` for details. Replaces ``document_correspondents``
|
||||
@@ -93,7 +659,7 @@ paperless-ng 0.9.0
|
||||
Certain language specifics such as umlauts may not get picked up properly.
|
||||
* ``PAPERLESS_DEBUG`` defaults to ``false``.
|
||||
* The presence of ``PAPERLESS_DBHOST`` now determines whether to use PostgreSQL or
|
||||
sqlite.
|
||||
SQLite.
|
||||
* ``PAPERLESS_OCR_THREADS`` is gone and replaced with ``PAPERLESS_TASK_WORKERS`` and
|
||||
``PAPERLESS_THREADS_PER_WORKER``. Refer to the config example for details.
|
||||
* ``PAPERLESS_OPTIMIZE_THUMBNAILS`` allows you to disable or enable thumbnail
|
||||
@@ -101,8 +667,11 @@ paperless-ng 0.9.0
|
||||
|
||||
* Many more small changes here and there. The usual stuff.
|
||||
|
||||
Paperless
|
||||
#########
|
||||
|
||||
2.7.0
|
||||
#####
|
||||
=====
|
||||
|
||||
* `syntonym`_ submitted a pull request to catch IMAP connection errors `#475`_.
|
||||
* `Stéphane Brunner`_ added ``psycopg2`` to the Pipfile `#489`_. He also fixed
|
||||
@@ -119,7 +688,7 @@ paperless-ng 0.9.0
|
||||
|
||||
|
||||
2.6.1
|
||||
#####
|
||||
=====
|
||||
|
||||
* We now have a logo, complete with a favicon :-)
|
||||
* Removed some problematic tests.
|
||||
@@ -131,7 +700,7 @@ paperless-ng 0.9.0
|
||||
|
||||
|
||||
2.6.0
|
||||
#####
|
||||
=====
|
||||
|
||||
* Allow an infinite number of logs to be deleted. Thanks to `Ulli`_ for noting
|
||||
the problem in `#433`_.
|
||||
@@ -152,7 +721,7 @@ paperless-ng 0.9.0
|
||||
|
||||
|
||||
2.5.0
|
||||
#####
|
||||
=====
|
||||
|
||||
* **New dependency**: Paperless now optimises thumbnail generation with
|
||||
`optipng`_, so you'll need to install that somewhere in your PATH or declare
|
||||
@@ -196,7 +765,7 @@ paperless-ng 0.9.0
|
||||
|
||||
|
||||
2.4.0
|
||||
#####
|
||||
=====
|
||||
|
||||
* A new set of actions are now available thanks to `jonaswinkler`_'s very first
|
||||
pull request! You can now do nifty things like tag documents in bulk, or set
|
||||
@@ -217,7 +786,7 @@ paperless-ng 0.9.0
|
||||
|
||||
|
||||
2.3.0
|
||||
#####
|
||||
=====
|
||||
|
||||
* Support for consuming plain text & markdown documents was added by
|
||||
`Joshua Taillon`_! This was a long-requested feature, and it's addition is
|
||||
@@ -235,14 +804,14 @@ paperless-ng 0.9.0
|
||||
|
||||
|
||||
2.2.1
|
||||
#####
|
||||
=====
|
||||
|
||||
* `Kyle Lucy`_ reported a bug quickly after the release of 2.2.0 where we broke
|
||||
the ``DISABLE_LOGIN`` feature: `#392`_.
|
||||
|
||||
|
||||
2.2.0
|
||||
#####
|
||||
=====
|
||||
|
||||
* Thanks to `dadosch`_, `Wolfgang Mader`_, and `Tim Brooks`_ this is the first
|
||||
version of Paperless that supports Django 2.0! As a result of their hard
|
||||
@@ -259,7 +828,7 @@ paperless-ng 0.9.0
|
||||
|
||||
|
||||
2.1.0
|
||||
#####
|
||||
=====
|
||||
|
||||
* `Enno Lohmeier`_ added three simple features that make Paperless a lot more
|
||||
user (and developer) friendly:
|
||||
@@ -278,7 +847,7 @@ paperless-ng 0.9.0
|
||||
|
||||
|
||||
2.0.0
|
||||
#####
|
||||
=====
|
||||
|
||||
This is a big release as we've changed a core-functionality of Paperless: we no
|
||||
longer encrypt files with GPG by default.
|
||||
@@ -310,7 +879,7 @@ Special thanks to `erikarvstedt`_, `matthewmoto`_, and `mcronce`_ who did the
|
||||
bulk of the work on this big change.
|
||||
|
||||
1.4.0
|
||||
#####
|
||||
=====
|
||||
|
||||
* `Quentin Dawans`_ has refactored the document consumer to allow for some
|
||||
command-line options. Notably, you can now direct it to consume from a
|
||||
@@ -345,7 +914,7 @@ bulk of the work on this big change.
|
||||
to some excellent work from `erikarvstedt`_ on `#351`_
|
||||
|
||||
1.3.0
|
||||
#####
|
||||
=====
|
||||
|
||||
* 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`_:
|
||||
@@ -368,7 +937,7 @@ bulk of the work on this big change.
|
||||
problem and helping me find where to fix it.
|
||||
|
||||
1.2.0
|
||||
#####
|
||||
=====
|
||||
|
||||
* New Docker image, now based on Alpine, thanks to the efforts of `addadi`_
|
||||
and `Pit`_. This new image is dramatically smaller than the Debian-based
|
||||
@@ -387,7 +956,7 @@ bulk of the work on this big change.
|
||||
in the document text.
|
||||
|
||||
1.1.0
|
||||
#####
|
||||
=====
|
||||
|
||||
* Fix for `#283`_, a redirect bug which broke interactions with
|
||||
paperless-desktop. Thanks to `chris-aeviator`_ for reporting it.
|
||||
@@ -397,7 +966,7 @@ bulk of the work on this big change.
|
||||
`Dan Panzarella`_
|
||||
|
||||
1.0.0
|
||||
#####
|
||||
=====
|
||||
|
||||
* Upgrade to Django 1.11. **You'll need to run
|
||||
``pip install -r requirements.txt`` after the usual ``git pull`` to
|
||||
@@ -416,14 +985,14 @@ bulk of the work on this big change.
|
||||
`Lukas Winkler`_'s issue `#278`_
|
||||
|
||||
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`_'s work on
|
||||
`#255`_.
|
||||
|
||||
0.7.0
|
||||
#####
|
||||
=====
|
||||
|
||||
* **Potentially breaking change**: As per `#235`_, Paperless will no longer
|
||||
automatically delete documents attached to correspondents when those
|
||||
@@ -435,7 +1004,7 @@ bulk of the work on this big change.
|
||||
`Kusti Skytén`_ for posting the correct solution in the Github issue.
|
||||
|
||||
0.6.0
|
||||
#####
|
||||
=====
|
||||
|
||||
* Abandon the shared-secret trick we were using for the POST API in favour
|
||||
of BasicAuth or Django session.
|
||||
@@ -449,7 +1018,7 @@ bulk of the work on this big change.
|
||||
the help with this feature.
|
||||
|
||||
0.5.0
|
||||
#####
|
||||
=====
|
||||
|
||||
* Support for fuzzy matching in the auto-tagger & auto-correspondent systems
|
||||
thanks to `Jake Gysland`_'s patch `#220`_.
|
||||
@@ -467,13 +1036,13 @@ bulk of the work on this big change.
|
||||
* Amended the Django Admin configuration to have nice headers (`#230`_)
|
||||
|
||||
0.4.1
|
||||
#####
|
||||
=====
|
||||
|
||||
* Fix for `#206`_ wherein the pluggable parser didn't recognise files with
|
||||
all-caps suffixes like ``.PDF``
|
||||
|
||||
0.4.0
|
||||
#####
|
||||
=====
|
||||
|
||||
* Introducing reminders. See `#199`_ for more information, but the short
|
||||
explanation is that you can now attach simple notes & times to documents
|
||||
@@ -483,7 +1052,7 @@ bulk of the work on this big change.
|
||||
like to make use of this feature in his project.
|
||||
|
||||
0.3.6
|
||||
#####
|
||||
=====
|
||||
|
||||
* Fix for `#200`_ (!!) where the API wasn't configured to allow updating the
|
||||
correspondent or the tags for a document.
|
||||
@@ -497,7 +1066,7 @@ bulk of the work on this big change.
|
||||
documentation is on its way.
|
||||
|
||||
0.3.5
|
||||
#####
|
||||
=====
|
||||
|
||||
* A serious facelift for the documents listing page wherein we drop the
|
||||
tabular layout in favour of a tiled interface.
|
||||
@@ -508,7 +1077,7 @@ bulk of the work on this big change.
|
||||
consumption.
|
||||
|
||||
0.3.4
|
||||
#####
|
||||
=====
|
||||
|
||||
* 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
|
||||
@@ -521,26 +1090,26 @@ bulk of the work on this big change.
|
||||
API thanks to @thomasbrueggemann. See `#179`_.
|
||||
|
||||
0.3.3
|
||||
#####
|
||||
=====
|
||||
|
||||
* Thumbnails in the UI and a Django-suit -based face-lift courtesy of @ekw!
|
||||
* Timezone, items per page, and default language are now all configurable,
|
||||
also thanks to @ekw.
|
||||
|
||||
0.3.2
|
||||
#####
|
||||
=====
|
||||
|
||||
* Fix for `#172`_: defaulting ALLOWED_HOSTS to ``["*"]`` and allowing the
|
||||
user to set her own value via ``PAPERLESS_ALLOWED_HOSTS`` should the need
|
||||
arise.
|
||||
|
||||
0.3.1
|
||||
#####
|
||||
=====
|
||||
|
||||
* Added a default value for ``CONVERT_BINARY``
|
||||
|
||||
0.3.0
|
||||
#####
|
||||
=====
|
||||
|
||||
* Updated to using django-filter 1.x
|
||||
* Added some system checks so new users aren't confused by misconfigurations.
|
||||
@@ -553,7 +1122,7 @@ bulk of the work on this big change.
|
||||
``PAPERLESS_SHARED_SECRET`` respectively instead.
|
||||
|
||||
0.2.0
|
||||
#####
|
||||
=====
|
||||
|
||||
* `#150`_: The media root is now a variable you can set in
|
||||
``paperless.conf``.
|
||||
@@ -581,7 +1150,7 @@ bulk of the work on this big change.
|
||||
to `Martin Honermeyer`_ and `Tim White`_ for working with me on this.
|
||||
|
||||
0.1.1
|
||||
#####
|
||||
=====
|
||||
|
||||
* Potentially **Breaking Change**: All references to "sender" in the code
|
||||
have been renamed to "correspondent" to better reflect the nature of the
|
||||
@@ -605,7 +1174,7 @@ bulk of the work on this big change.
|
||||
to be imported but made unavailable.
|
||||
|
||||
0.1.0
|
||||
#####
|
||||
=====
|
||||
|
||||
* Docker support! Big thanks to `Wayne Werner`_, `Brian Conn`_, and
|
||||
`Tikitu de Jager`_ for this one, and especially to `Pit`_
|
||||
@@ -624,14 +1193,14 @@ bulk of the work on this big change.
|
||||
* Added tox with pep8 checking
|
||||
|
||||
0.0.6
|
||||
#####
|
||||
=====
|
||||
|
||||
* Added support for parallel OCR (significant work from `Pit`_)
|
||||
* Sped up the language detection (significant work from `Pit`_)
|
||||
* Added simple logging
|
||||
|
||||
0.0.5
|
||||
#####
|
||||
=====
|
||||
|
||||
* Added support for image files as documents (png, jpg, gif, tiff)
|
||||
* Added a crude means of HTTP POST for document imports
|
||||
@@ -640,7 +1209,7 @@ bulk of the work on this big change.
|
||||
* Documentation for the above as well as data migration
|
||||
|
||||
0.0.4
|
||||
#####
|
||||
=====
|
||||
|
||||
* Added automated tagging basted on keyword matching
|
||||
* Cleaned up the document listing page
|
||||
@@ -648,22 +1217,28 @@ bulk of the work on this big change.
|
||||
* Added ``pytz`` to the list of requirements
|
||||
|
||||
0.0.3
|
||||
#####
|
||||
=====
|
||||
|
||||
* Added basic tagging
|
||||
|
||||
0.0.2
|
||||
#####
|
||||
=====
|
||||
|
||||
* Added language detection
|
||||
* Added datestamps to ``document_exporter``.
|
||||
* Changed ``settings.TESSERACT_LANGUAGE`` to ``settings.OCR_LANGUAGE``.
|
||||
|
||||
0.0.1
|
||||
#####
|
||||
=====
|
||||
|
||||
* Initial release
|
||||
|
||||
.. _slorenz: https://github.com/sisao
|
||||
.. _Jo Vandeginste: https://github.com/jovandeginste
|
||||
.. _zjean: https://github.com/zjean
|
||||
.. _rYR79435: https://github.com/rYR79435
|
||||
.. _Michael Shamoon: https://github.com/shamoon
|
||||
.. _jayme-github: http://github.com/jayme-github
|
||||
.. _Brian Conn: https://github.com/TheConnMan
|
||||
.. _Christopher Luu: https://github.com/nuudles
|
||||
.. _Florian Jung: https://github.com/the01
|
||||
|
53
docs/conf.py
@@ -1,48 +1,21 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Paperless documentation build configuration file, created by
|
||||
# sphinx-quickstart on Mon Oct 26 18:36:52 2015.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its
|
||||
# containing dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
import sphinx_rtd_theme
|
||||
|
||||
|
||||
__version__ = None
|
||||
exec(open("../src/paperless/version.py").read())
|
||||
|
||||
|
||||
# Believe it or not, this is the officially sanctioned way to add custom CSS.
|
||||
def setup(app):
|
||||
app.add_stylesheet("custom.css")
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.intersphinx',
|
||||
'sphinx.ext.todo',
|
||||
'sphinx.ext.imgmath',
|
||||
'sphinx.ext.viewcode',
|
||||
'sphinx_rtd_theme',
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
# templates_path = ['_templates']
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
@@ -55,7 +28,7 @@ master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'Paperless-ng'
|
||||
copyright = u'2015, Daniel Quinn'
|
||||
copyright = u'2021, Daniel Quinn, Jonas Winkler'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
@@ -115,7 +88,7 @@ pygments_style = 'sphinx'
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'default'
|
||||
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
|
||||
@@ -195,20 +168,6 @@ html_static_path = ['_static']
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'paperless'
|
||||
|
||||
|
||||
#
|
||||
# Attempt to use the ReadTheDocs theme. If it's not installed, fallback to
|
||||
# the default.
|
||||
#
|
||||
|
||||
try:
|
||||
import sphinx_rtd_theme
|
||||
html_theme = "sphinx_rtd_theme"
|
||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
|
||||
except ImportError as e:
|
||||
print("error " + str(e))
|
||||
pass
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
|
@@ -1,9 +1,10 @@
|
||||
.. _configuration:
|
||||
|
||||
*************
|
||||
Configuration
|
||||
*************
|
||||
|
||||
Paperless provides a wide range of customizations.
|
||||
Have a look at ``paperless.conf.example`` for available configuration options.
|
||||
Depending on how you run paperless, these settings have to be defined in different
|
||||
places.
|
||||
|
||||
@@ -18,5 +19,647 @@ places.
|
||||
/etc/paperless.conf
|
||||
/usr/local/etc/paperless.conf
|
||||
|
||||
Copy ``paperless.conf.example`` to any of these locations and adjust it to your
|
||||
needs.
|
||||
|
||||
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.
|
||||
|
||||
Defaults to redis://localhost:6379.
|
||||
|
||||
PAPERLESS_DBHOST=<hostname>
|
||||
By default, sqlite is used as the database backend. This can be changed here.
|
||||
Set PAPERLESS_DBHOST and PostgreSQL will be used instead of mysql.
|
||||
|
||||
PAPERLESS_DBPORT=<port>
|
||||
Adjust port if necessary.
|
||||
|
||||
Default is 5432.
|
||||
|
||||
PAPERLESS_DBNAME=<name>
|
||||
Database name in PostgreSQL.
|
||||
|
||||
Defaults to "paperless".
|
||||
|
||||
PAPERLESS_DBUSER=<name>
|
||||
Database user in PostgreSQL.
|
||||
|
||||
Defaults to "paperless".
|
||||
|
||||
PAPERLESS_DBPASS=<password>
|
||||
Database password for PostgreSQL.
|
||||
|
||||
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``.
|
||||
|
||||
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_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_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 & 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_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,"
|
||||
|
||||
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.
|
||||
|
||||
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!
|
||||
|
||||
.. note::
|
||||
|
||||
I don't know if this works in paperless-ng. Probably not.
|
||||
|
||||
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.
|
||||
|
||||
Defaults to "/static/".
|
||||
|
||||
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_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.
|
||||
|
||||
Defaults to `false` 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".
|
||||
|
||||
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 pages 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 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_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 dashed.
|
||||
|
||||
.. 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://thecodingmachine.github.io/gotenberg/>`_ 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.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: thecodingmachine/gotenberg
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
DISABLE_GOOGLE_CHROME: 1
|
||||
|
||||
tika:
|
||||
image: apache/tika
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
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_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_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_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_OPTIMIZE_THUMBNAILS=<bool>
|
||||
Use optipng to optimize thumbnails. This usually reduces the size of
|
||||
thumbnails by about 20%, but uses considerable compute time during
|
||||
consumption.
|
||||
|
||||
Defaults to true.
|
||||
|
||||
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.
|
||||
|
||||
Defaults to none, which disables 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.
|
||||
|
||||
You may specify dates in a multitude of formats supported by dateparser (see
|
||||
https://dateparser.readthedocs.io/en/latest/#popular-formats) but as the dates
|
||||
need to be comma separated, the options are limited.
|
||||
Example: "2020-12-02,22.04.1999"
|
||||
|
||||
Defaults to an empty string to not ignore any dates.
|
||||
|
||||
|
||||
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 "/usr/bin/convert".
|
||||
|
||||
PAPERLESS_GS_BINARY=<path>
|
||||
Defaults to "/usr/bin/gs".
|
||||
|
||||
PAPERLESS_OPTIPNG_BINARY=<path>
|
||||
Defaults to "/usr/bin/optipng".
|
||||
|
||||
|
||||
.. _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.
|
||||
|
||||
Consider configuring this to 1 on low power devices with limited amount of RAM.
|
||||
|
||||
Defaults to 2.
|
||||
|
||||
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.
|
||||
|
@@ -85,7 +85,7 @@ quoted, or triple-quoted string will do:
|
||||
problematic_string = 'This is a "string" with "quotes" in it'
|
||||
|
||||
In HTML templates, please use double-quotes for tag attributes, and single
|
||||
quotes for arguments passed to Django tempalte tags:
|
||||
quotes for arguments passed to Django template tags:
|
||||
|
||||
.. code:: html
|
||||
|
||||
|
@@ -1,116 +1,215 @@
|
||||
.. _extending:
|
||||
|
||||
Paperless development
|
||||
#####################
|
||||
|
||||
This section describes the steps you need to take to start development on paperless-ng.
|
||||
|
||||
1. Check out the source from github. The repository is organized in the following way:
|
||||
|
||||
* ``master`` 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.
|
||||
|
||||
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.
|
||||
|
||||
2. Install some dependencies.
|
||||
|
||||
* Python 3.6.
|
||||
* All dependencies listed in the :ref:`Bare metal route <setup-bare_metal>`
|
||||
* redis. You can either install redis or use the included scritps/start-services.sh
|
||||
to use docker to fire up a redis instance (and some other services such as tika,
|
||||
gotenberg and a postgresql server).
|
||||
|
||||
Back end development
|
||||
====================
|
||||
|
||||
The backend is a django application. I use PyCharm for development, but you can use whatever
|
||||
you want.
|
||||
|
||||
Install the python dependencies by performing ``pipenv install --dev`` in the src/ directory.
|
||||
This will also create a virtual environment, which you can enter with ``pipenv shell`` or
|
||||
execute one-shot commands in with ``pipenv run``.
|
||||
|
||||
Copy ``paperless.conf.example`` to ``paperless.conf`` and enable debug mode.
|
||||
|
||||
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
|
||||
* python3 manage.py qcluster
|
||||
* python3 manage.py consumer
|
||||
|
||||
Depending on which part of paperless you're developing for, you need to have some or all of
|
||||
them running.
|
||||
|
||||
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.
|
||||
* Run ``pycodestyle`` to test your code for issues with the configured code style settings.
|
||||
|
||||
.. 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 build using angular. I use the ``Code - OSS`` IDE for development.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
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.
|
||||
|
||||
Extending Paperless
|
||||
===================
|
||||
|
||||
.. warning::
|
||||
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.
|
||||
|
||||
This section is not updated to paperless-ng yet.
|
||||
Making custom parsers
|
||||
---------------------
|
||||
|
||||
For the most part, Paperless is monolithic, so extending it is often best
|
||||
managed by way of modifying the code directly and issuing a pull request on
|
||||
`GitHub`_. However, over time the project has been evolving to be a little
|
||||
more "pluggable" so that users can write their own stuff that talks to it.
|
||||
Paperless uses parsers to add documents to paperless. A parser is responsible for:
|
||||
|
||||
.. _GitHub: https://github.com/the-paperless-project/paperless
|
||||
* 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.
|
||||
|
||||
.. _extending-parsers:
|
||||
|
||||
Parsers
|
||||
-------
|
||||
|
||||
You can leverage Paperless' consumption model to have it consume files *other*
|
||||
than ones handled by default like ``.pdf``, ``.jpg``, and ``.tiff``. To do so,
|
||||
you simply follow Django's convention of creating a new app, with a few key
|
||||
requirements.
|
||||
|
||||
|
||||
.. _extending-parsers-parserspy:
|
||||
|
||||
parsers.py
|
||||
..........
|
||||
|
||||
In this file, you create a class that extends
|
||||
``documents.parsers.DocumentParser`` and go about implementing the three
|
||||
required methods:
|
||||
|
||||
* ``get_thumbnail()``: Returns the path to a file we can use as a thumbnail for
|
||||
this document.
|
||||
* ``get_text()``: Returns the text from the document and only the text.
|
||||
* ``get_date()``: If possible, this returns the date of the document, otherwise
|
||||
it should return ``None``.
|
||||
|
||||
|
||||
.. _extending-parsers-signalspy:
|
||||
|
||||
signals.py
|
||||
..........
|
||||
|
||||
At consumption time, Paperless emits a ``document_consumer_declaration``
|
||||
signal which your module has to react to in order to let the consumer know
|
||||
whether or not it's capable of handling a particular file. Think of it like
|
||||
this:
|
||||
|
||||
1. Consumer finds a file in the consumption directory.
|
||||
2. It asks all the available parsers: *"Hey, can you handle this file?"*
|
||||
3. Each parser responds with either ``None`` meaning they can't handle the
|
||||
file, or a dictionary in the following format:
|
||||
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
|
||||
|
||||
{
|
||||
"parser": <the class name>,
|
||||
"weight": <an integer>
|
||||
}
|
||||
class MyCustomParser(DocumentParser):
|
||||
|
||||
The consumer compares the ``weight`` values from all respondents and uses the
|
||||
class with the highest value to consume the document. The default parser,
|
||||
``RasterisedDocumentParser`` has a weight of ``0``.
|
||||
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")
|
||||
|
||||
.. _extending-parsers-appspy:
|
||||
# Optional: "created" date of the document.
|
||||
self.date = get_created_from_metadata(document_path)
|
||||
|
||||
apps.py
|
||||
.......
|
||||
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")
|
||||
|
||||
This is a standard Django file, but you'll need to add some code to it to
|
||||
connect your parser to the ``document_consumer_declaration`` signal.
|
||||
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.
|
||||
|
||||
.. _extending-parsers-finally:
|
||||
|
||||
Finally
|
||||
.......
|
||||
|
||||
The last step is to update ``settings.py`` to include your new module.
|
||||
Eventually, this will be dynamic, but at the moment, you have to edit the
|
||||
``INSTALLED_APPS`` section manually. Simply add the path to your AppConfig to
|
||||
the list like this:
|
||||
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
|
||||
|
||||
INSTALLED_APPS = [
|
||||
...
|
||||
"my_module.apps.MyModuleConfig",
|
||||
...
|
||||
]
|
||||
def myparser_consumer_declaration(sender, **kwargs):
|
||||
return {
|
||||
"parser": MyCustomParser,
|
||||
"weight": 0,
|
||||
"mime_types": {
|
||||
"application/pdf": ".pdf",
|
||||
"image/jpeg": ".jpg",
|
||||
}
|
||||
}
|
||||
|
||||
Order doesn't matter, but generally it's a good idea to place your module lower
|
||||
in the list so that you don't end up accidentally overriding project defaults
|
||||
somewhere.
|
||||
* ``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.
|
||||
|
||||
.. _extending-parsers-example:
|
||||
|
||||
An Example
|
||||
..........
|
||||
|
||||
The core Paperless functionality is based on this design, so if you want to see
|
||||
what a parser module should look like, have a look at `parsers.py`_,
|
||||
`signals.py`_, and `apps.py`_ in the `paperless_tesseract`_ module.
|
||||
|
||||
.. _parsers.py: https://github.com/the-paperless-project/paperless/blob/master/src/paperless_tesseract/parsers.py
|
||||
.. _signals.py: https://github.com/the-paperless-project/paperless/blob/master/src/paperless_tesseract/signals.py
|
||||
.. _apps.py: https://github.com/the-paperless-project/paperless/blob/master/src/paperless_tesseract/apps.py
|
||||
.. _paperless_tesseract: https://github.com/the-paperless-project/paperless/blob/master/src/paperless_tesseract/
|
||||
* ``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.
|
||||
|
109
docs/faq.rst
@@ -3,6 +3,18 @@
|
||||
Frequently asked questions
|
||||
**************************
|
||||
|
||||
**Q:** *What's the general plan for Paperless-ng?*
|
||||
|
||||
**A:** Paperless-ng is already almost feature-complete. This project will remain
|
||||
as simple as it is right now. It will see improvements to features that are already there.
|
||||
If you need advanced features such as document versions,
|
||||
workflows or multi-user with customizable access to individual files, this is
|
||||
not the tool for you.
|
||||
|
||||
Features that *are* planned are some more quality of life extensions for the searching
|
||||
(i.e., search for similar documents, group results by correspondents with "more from this"
|
||||
links, etc), bulk editing and hierarchical tags.
|
||||
|
||||
**Q:** *I'm using docker. Where are my documents?*
|
||||
|
||||
**A:** Your documents are stored inside the docker volume ``paperless_media``.
|
||||
@@ -17,41 +29,94 @@ is
|
||||
|
||||
.. caution::
|
||||
|
||||
Dont mess with this folder. Don't change permissions and don't move
|
||||
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 you don't support this project anymore 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 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-ng 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 determines the type of a file by inspecting its content. The
|
||||
file extensions do not matter.
|
||||
|
||||
**Q:** *Will paperless-ng 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 tesseract OCR. On Rasperry Pi,
|
||||
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 should be alot snappier, since it runs
|
||||
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::
|
||||
|
||||
Consider setting ``PAPERLESS_OPTIMIZE_THUMBNAILS`` to false to speed up
|
||||
the consumption process. This takes quite a bit of time on Raspberry Pi.
|
||||
|
||||
.. 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 or weekly. 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.
|
||||
|
||||
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-ng on Raspberry Pi?*
|
||||
|
||||
**A:** There is not docker image for ARM available. If you know how to build
|
||||
that automatically, I'm all ears. For now, you have to grab the latest release
|
||||
archive from the project page and build the image yourself. The release comes
|
||||
with the front end already compiled, so you don't have to do this on the 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:** Head over to `<https://github.com/selfhosters/unRAID-CA-templates>`_,
|
||||
`Uli Fahrer <https://github.com/Tooa>`_ created a container template for that.
|
||||
I don't exactly know how to use that though, since I don't use unRaid.
|
||||
|
||||
**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
|
||||
|
@@ -25,14 +25,34 @@ and then shred them. Perhaps you might find it useful too.
|
||||
Paperless-ng
|
||||
============
|
||||
|
||||
I wanted to make big changes to the project that will impact the way it is used
|
||||
by its users greatly. Among the users who currently use paperless in production
|
||||
there are probably many that don't want these changes right away. I also wanted
|
||||
to have more control over what goes into the code and what does not. Therefore,
|
||||
paperless-ng was created. NG stands for both Angular (the framework used for the
|
||||
Paperless-ng is a fork of the original paperless project. It changes many
|
||||
things both on the surface and under the hood. Paperless-ng was created
|
||||
because I feel that these changes are too big to be pushed into the main
|
||||
repository right away.
|
||||
|
||||
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-ng.
|
||||
|
||||
If you want to learn about what's different in paperless-ng, 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 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-ng.
|
||||
* 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 :ref:`changelog <paperless_changelog>` contains a detailed list of all changes
|
||||
in paperless-ng.
|
||||
|
||||
It would be great if this project could eventually merge back into the main
|
||||
repository, but it needs a lot more work before that can happen.
|
||||
|
||||
@@ -50,8 +70,8 @@ Contents
|
||||
configuration
|
||||
api
|
||||
faq
|
||||
extending
|
||||
troubleshooting
|
||||
extending
|
||||
contributing
|
||||
scanners
|
||||
screenshots
|
||||
|
@@ -8,7 +8,10 @@ Scanner recommendations
|
||||
As Paperless operates by watching a folder for new files, doesn't care what
|
||||
scanner you use, but sometimes finding a scanner that will write to an FTP,
|
||||
NFS, or SMB server can be difficult. This page is here to help you find one
|
||||
that works right for you based on recommentations from other Paperless users.
|
||||
that works right for you based on recommendations from other Paperless users.
|
||||
|
||||
Physical scanners
|
||||
=================
|
||||
|
||||
+---------+----------------+-----+-----+-----+----------------+
|
||||
| Brand | Model | Supports | Recommended By |
|
||||
@@ -25,6 +28,8 @@ that works right for you based on recommentations from other Paperless users.
|
||||
+---------+----------------+-----+-----+-----+----------------+
|
||||
| Fujitsu | `ix500`_ | yes | | yes | `eonist`_ |
|
||||
+---------+----------------+-----+-----+-----+----------------+
|
||||
| Epson | `WF-7710DWF`_ | yes | | yes | `Skylinar`_ |
|
||||
+---------+----------------+-----+-----+-----+----------------+
|
||||
| Fujitsu | `S1300i`_ | yes | | yes | `jonaswinkler`_|
|
||||
+---------+----------------+-----+-----+-----+----------------+
|
||||
|
||||
@@ -32,7 +37,8 @@ that works right for you based on recommentations from other Paperless users.
|
||||
.. _MFC-J6930DW: https://www.brother.ca/en/p/MFCJ6930DW
|
||||
.. _MFC-J5910DW: https://www.brother.co.uk/printers/inkjet-printers/mfcj5910dw
|
||||
.. _MFC-9142CDN: https://www.brother.co.uk/printers/laser-printers/mfc9140cdn
|
||||
.. _ix500: https://www.fujitsu.com/global/products/computing/peripheral/scanners/scansnap/ix500/
|
||||
.. _ix500: http://www.fujitsu.com/us/products/computing/peripheral/scanners/scansnap/ix500/
|
||||
.. _WF-7710DWF: https://www.epson.de/en/products/printers/inkjet-printers/for-home/workforce-wf-7710dwf
|
||||
.. _S1300i: https://www.fujitsu.com/global/products/computing/peripheral/scanners/soho/s1300i/
|
||||
|
||||
.. _danielquinn: https://github.com/danielquinn
|
||||
@@ -40,4 +46,27 @@ that works right for you based on recommentations from other Paperless users.
|
||||
.. _bmsleight: https://github.com/bmsleight
|
||||
.. _eonist: https://github.com/eonist
|
||||
.. _REOLDEV: https://github.com/REOLDEV
|
||||
.. _Skylinar: https://github.com/Skylinar
|
||||
.. _jonaswinkler: https://github.com/jonaswinkler
|
||||
|
||||
Mobile phone software
|
||||
=====================
|
||||
|
||||
You can use your phone to "scan" documents. The regular camera app will work, but may have too low contrast for OCR to work well. Apps specifically for scanning are recommended.
|
||||
|
||||
+-------------------+----------------+-----+-----+-----+-------+--------+----------------+
|
||||
| Name | OS | Supports | Recommended By |
|
||||
+-------------------+----------------+-----+-----+-----+-------+--------+----------------+
|
||||
| | | FTP | NFS | SMB | Email | WebDav | |
|
||||
+===================+================+=====+=====+=====+=======+========+================+
|
||||
| `Office Lens`_ | Android | ? | ? | ? | ? | ? | `jonaswinkler`_|
|
||||
+-------------------+----------------+-----+-----+-----+-------+--------+----------------+
|
||||
| `Genius Scan`_ | Android | yes | no | yes | yes | yes | `hannahswain`_ |
|
||||
+-------------------+----------------+-----+-----+-----+-------+--------+----------------+
|
||||
|
||||
On Android, you can use these applications in combination with one of the :ref:`Paperless-ng compatible apps <usage-mobile_upload>` to "Share" the documents produced by these scanner apps with paperless.
|
||||
|
||||
.. _Office Lens: https://play.google.com/store/apps/details?id=com.microsoft.office.officelens
|
||||
.. _Genius Scan: https://play.google.com/store/apps/details?id=com.thegrizzlylabs.geniusscan.free
|
||||
|
||||
.. _hannahswain: https://github.com/hannahswain
|
||||
|
@@ -1,3 +1,5 @@
|
||||
.. _screenshots:
|
||||
|
||||
***********
|
||||
Screenshots
|
||||
***********
|
||||
@@ -7,40 +9,37 @@ research papers though, its a horrible tool for that job.
|
||||
|
||||
The dashboard shows customizable views on your document and allows document uploads:
|
||||
|
||||
.. image:: _static/paperless-0-dashboard.png
|
||||
.. image:: _static/screenshots/dashboard.png
|
||||
|
||||
The document list provides three different styles to scroll through your documents:
|
||||
|
||||
.. image:: _static/paperless-1-list-table.png
|
||||
.. image:: _static/paperless-2-list-smallcards.png
|
||||
.. image:: _static/paperless-3-list-largecards.png
|
||||
.. image:: _static/screenshots/documents-table.png
|
||||
.. image:: _static/screenshots/documents-smallcards.png
|
||||
.. image:: _static/screenshots/documents-largecards.png
|
||||
|
||||
Extensive filtering mechanisms:
|
||||
|
||||
.. image:: _static/paperless-4-filter.png
|
||||
.. image:: _static/screenshots/documents-filter.png
|
||||
|
||||
Side-by-side editing of documents. Optmized for 1080p.
|
||||
Side-by-side editing of documents. Optimized for 1080p.
|
||||
|
||||
.. image:: _static/paperless-5-editing.png
|
||||
.. image:: _static/screenshots/editing.png
|
||||
|
||||
Tag editing. This looks about the same for correspondents and document types.
|
||||
|
||||
.. image:: _static/paperless-6-tags.png
|
||||
.. image:: _static/screenshots/new-tag.png
|
||||
|
||||
Searching provides auto complete and highlights the results.
|
||||
|
||||
.. image:: _static/paperless-7-autocomplete.png
|
||||
.. image:: _static/paperless-8-search-results.png
|
||||
|
||||
The old admin is still there and accessible!
|
||||
|
||||
.. image:: _static/paperless-9-admin.png
|
||||
.. image:: _static/screenshots/search-preview.png
|
||||
.. image:: _static/screenshots/search-results.png
|
||||
|
||||
Fancy mail filters!
|
||||
|
||||
.. image:: _static/paperless-11-mail-filters.png
|
||||
.. image:: _static/screenshots/mail-rules-edited.png
|
||||
|
||||
Mobile support in the future? This doesn't really work yet.
|
||||
Mobile support in the future? This kinda works, however some layouts are still
|
||||
too wide.
|
||||
|
||||
.. image:: _static/paperless-10-mobile.png
|
||||
.. image:: _static/screenshots/mobile.png
|
||||
|
||||
|
790
docs/setup.rst
@@ -3,162 +3,205 @@
|
||||
Setup
|
||||
*****
|
||||
|
||||
Download
|
||||
########
|
||||
|
||||
Go to the project page on GitHub and download the
|
||||
`latest release <https://github.com/jonaswinkler/paperless-ng/releases>`_.
|
||||
There are multiple options available.
|
||||
|
||||
* Download the docker-compose files if you want to pull paperless from
|
||||
Docker Hub.
|
||||
|
||||
* Download the archive and extract it if you want to build the docker image
|
||||
yourself or want to install paperless without docker.
|
||||
|
||||
.. hint::
|
||||
|
||||
In contrast to paperless, the recommended way to get and update paperless-ng
|
||||
is not to pull the entire git repository. Paperless-ng includes artifacts
|
||||
that need to be compiled, and that's already done for you in the release.
|
||||
|
||||
|
||||
Overview of Paperless-ng
|
||||
########################
|
||||
|
||||
Compared to paperless, paperless-ng 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.
|
||||
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 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/
|
||||
$ pipenv run gunicorn -c /usr/src/paperless/gunicorn.conf.py -b 0.0.0.0:8000 paperless.wsgi
|
||||
|
||||
$ 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 consume really consume your documents anymore.
|
||||
It rather notifies a task processor that a new file is ready for consumption.
|
||||
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 also used to check your emails, but that's now gone elsewhere as well.
|
||||
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/
|
||||
$ pipenv run python3 manage.py document_consumer
|
||||
$ python3 manage.py document_consumer
|
||||
|
||||
.. _setup-task_processor:
|
||||
|
||||
* **The task processor:** Paperless relies on `Django Q <https://django-q.readthedocs.io/en/latest/>`_
|
||||
for doing much of the heavy lifting. This is a task queue that accepts tasks from
|
||||
multiple sources and processes tasks in parallel. It also comes with a scheduler that executes
|
||||
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.
|
||||
* Consuming emails. It periodically checks your configured accounts for new mails and
|
||||
produces consumption tasks for any documents it finds.
|
||||
* The task processor also performs the consumption of any documents you upload through
|
||||
the web interface.
|
||||
* Maintain the search index and the automatic matching algorithm. These are things that paperless
|
||||
* 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 multicore system, consumption with full ocr is blazing fast.
|
||||
|
||||
The task processor comes with a built-in admin interface that you can use to see whenever any of the
|
||||
tasks fail and inspect the errors.
|
||||
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).
|
||||
|
||||
You may start the task processor by executing:
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
|
||||
$ cd /path/to/paperless/src/
|
||||
$ pipenv run python3 manage.py qcluster
|
||||
$ python3 manage.py qcluster
|
||||
|
||||
* A `redis <https://redis.io/>`_ message broker: This is a really lightweight service that is responsible
|
||||
for getting the tasks from the webserver and consumer to the task scheduler. These run in different
|
||||
processes (maybe even on different machines!), and therefore, this is necessary.
|
||||
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.
|
||||
|
||||
* A database server. Paperless supports PostgreSQL and sqlite for storing its data. However, with the
|
||||
added concurrency, it is strongly advised to use PostgreSQL, as sqlite has its limits in that regard.
|
||||
* Optional: A database server. Paperless supports both PostgreSQL and SQLite for storing its data.
|
||||
|
||||
|
||||
Installation
|
||||
############
|
||||
|
||||
You can go multiple routes with setting up and running Paperless:
|
||||
You can go multiple routes to setup and run Paperless:
|
||||
|
||||
* The `docker route`_
|
||||
* The `bare metal route`_
|
||||
* :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>`
|
||||
* :ref:`Use ansible to install Paperless on your system automatically (bare metal) <setup-ansible>`
|
||||
|
||||
The `docker route`_ is quick & easy. This is the recommended route. This configures all the stuff
|
||||
from above automatically so that it just works and uses sensible defaults for all configuration options.
|
||||
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://sehn.tech/post/devops-with-docker/>`_
|
||||
|
||||
The `bare metal route`_ is more complicated to setup but makes it easier
|
||||
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 Route
|
||||
============
|
||||
The ansible route combines benefits of both options:
|
||||
the setup process is fully automated, reproducible and `idempotent <https://docs.ansible.com/ansible/latest/reference_appendices/glossary.html#Idempotency>`_,
|
||||
it includes the same sensible defaults, and it simultaneously provides the flexibility of a bare metal installation.
|
||||
|
||||
1. Install `Docker`_ and `docker-compose`_. [#compose]_
|
||||
.. _CLI Basics: https://sehn.tech/post/devops-with-docker/
|
||||
.. _idempotent: https://docs.ansible.com/ansible/latest/reference_appendices/glossary.html#Idempotency
|
||||
|
||||
.. _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
|
||||
|
||||
$ wget https://raw.githubusercontent.com/jonaswinkler/paperless-ng/master/install-paperless-ng.sh
|
||||
$ chmod +x install-paperless-ng.sh
|
||||
$ ./install-paperless-ng.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-ng` 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/jonaswinkler/paperless-ng/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.example`` file, you
|
||||
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 an up-to-date version of docker-compose, follow the
|
||||
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/
|
||||
|
||||
2. Modify ``docker-compose.yml`` to your preferences. You should change the path
|
||||
to the consumption directory in this file. Find the line that specifies where
|
||||
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.
|
||||
|
||||
|
||||
3. Modify ``docker-compose.env``, following the comments in the file. The
|
||||
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. This ensures that
|
||||
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.
|
||||
work out of the box without any modifications. `id "username"` to check.
|
||||
|
||||
4. Run ``docker-compose up -d``. This will create and start the necessary
|
||||
containers. This will also build the image of paperless if you grabbed the
|
||||
source archive.
|
||||
.. note::
|
||||
|
||||
5. To be able to login, you will need a super user. To create it, execute the
|
||||
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.
|
||||
|
||||
.. 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
|
||||
@@ -166,45 +209,368 @@ Docker Route
|
||||
$ docker-compose run --rm webserver createsuperuser
|
||||
|
||||
This will prompt you to set a username, an optional e-mail address and
|
||||
finally a password.
|
||||
finally a password (at least 8 characters).
|
||||
|
||||
6. The default ``docker-compose.yml`` exports the webserver on your local port
|
||||
8000. If you haven't adapted this, you should now be able to visit your
|
||||
Paperless instance at ``http://127.0.0.1:8000``. You can login with the
|
||||
user and password you just created.
|
||||
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/
|
||||
|
||||
.. [#compose] You of course don't have to use docker-compose, but it
|
||||
simplifies deployment immensely. If you know your way around Docker, feel
|
||||
free to tinker around without using compose!
|
||||
.. _setup-docker_build:
|
||||
|
||||
Build the Docker image yourself
|
||||
===============================
|
||||
|
||||
1. Clone the entire repository of paperless:
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
git clone https://github.com/jonaswinkler/paperless-ng
|
||||
|
||||
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: jonaswinkler/paperless-ng: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: .
|
||||
|
||||
4. Run the ``compile-frontend.sh`` script. This requires ``node`` and ``npm >= v15``.
|
||||
|
||||
5. 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
|
||||
================
|
||||
|
||||
.. warning::
|
||||
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.
|
||||
|
||||
TBD. User docker for now.
|
||||
1. Install dependencies. Paperless requires the following packages.
|
||||
|
||||
* ``python3`` 3.6, 3.7, 3.8, 3.9
|
||||
* ``python3-pip``
|
||||
* ``python3-dev``
|
||||
|
||||
* ``fonts-liberation`` for generating thumbnails for plain text files
|
||||
* ``imagemagick`` >= 6 for PDF conversion
|
||||
* ``optipng`` for optimizing thumbnails
|
||||
* ``gnupg`` for handling encrypted documents
|
||||
* ``libpq-dev`` for PostgreSQL
|
||||
* ``libmagic-dev`` for mime type detection
|
||||
* ``mime-support`` for mime type detection
|
||||
|
||||
These dependencies are required for OCRmyPDF, which is used for text recognition.
|
||||
|
||||
* ``unpaper``
|
||||
* ``ghostscript``
|
||||
* ``icc-profiles-free``
|
||||
* ``qpdf``
|
||||
* ``liblept5``
|
||||
* ``libxml2``
|
||||
* ``pngquant``
|
||||
* ``zlib1g``
|
||||
* ``tesseract-ocr`` >= 4.0.0 for OCR
|
||||
* ``tesseract-ocr`` language packs (``tesseract-ocr-eng``, ``tesseract-ocr-deu``, etc)
|
||||
|
||||
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`` >= 5.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, SQLite is available as well.
|
||||
|
||||
4. Get the release archive from `<https://github.com/jonaswinkler/paperless-ng/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_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.
|
||||
|
||||
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.
|
||||
|
||||
.. 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, and the ``scheduler``
|
||||
script to run tasks such as email checking and document consumption.
|
||||
|
||||
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.
|
||||
|
||||
.. _setup-ansible:
|
||||
|
||||
Install Paperless using ansible
|
||||
===============================
|
||||
|
||||
.. note::
|
||||
|
||||
This role currently only supports Debian 10 Buster and Ubuntu 20.04 Focal or later as target hosts.
|
||||
|
||||
1. Install ansible 2.7+ on the management node.
|
||||
This may be the target host paperless-ng is being installed on or any remote host which can access the target host.
|
||||
For further details, check the ansible `inventory <https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html>`_ documentation.
|
||||
|
||||
On Debian and Ubuntu, the official repositories should provide a suitable version:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
apt install ansible
|
||||
ansible --version
|
||||
|
||||
Alternatively, you can install the most recent ansible release using PyPI:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
python3 -m pip install ansible
|
||||
ansible --version
|
||||
|
||||
Make sure your taget hosts are accessible:
|
||||
|
||||
.. code:: sh
|
||||
|
||||
ansible -m ping YourAnsibleTargetHostGoesHere
|
||||
|
||||
2. Clone the repository of paperless-ng:
|
||||
|
||||
.. code:: sh
|
||||
|
||||
git clone https://github.com/jonaswinkler/paperless-ng
|
||||
|
||||
Checkout the latest release tag:
|
||||
|
||||
.. code:: sh
|
||||
|
||||
cd paperless-ng
|
||||
git checkout ng-1.0.0
|
||||
|
||||
3. Create an ansible ``playbook.yml`` in the paperless-ng root directory:
|
||||
|
||||
.. code:: yaml
|
||||
|
||||
- hosts: YourAnsibleTargetHostGoesHere
|
||||
become: yes
|
||||
vars_files:
|
||||
- ansible/vars.yml
|
||||
roles:
|
||||
- ansible
|
||||
|
||||
Optional: If you also want to use PostgreSQL on the target system, install and add (for example) the `geerlingguy.postgresql <https://github.com/geerlingguy/ansible-role-postgresql>`_ role:
|
||||
|
||||
.. code:: sh
|
||||
|
||||
ansible-galaxy install geerlingguy.postgresql
|
||||
|
||||
.. code:: yaml
|
||||
|
||||
- hosts: YourAnsibleTargetHostGoesHere
|
||||
become: yes
|
||||
vars_files:
|
||||
- ansible/vars.yml
|
||||
roles:
|
||||
- geerlingguy.postgresql
|
||||
- ansible
|
||||
|
||||
Optional: If you also want to use a reverse proxy on the target system, install and add (for example) the `geerlingguy.nginx <https://github.com/geerlingguy/ansible-role-nginx>`_ role:
|
||||
|
||||
.. code:: sh
|
||||
|
||||
ansible-galaxy install geerlingguy.nginx
|
||||
|
||||
.. code:: yaml
|
||||
|
||||
- hosts: YourAnsibleTargetHostGoesHere
|
||||
become: yes
|
||||
vars_files:
|
||||
- ansible/vars.yml
|
||||
roles:
|
||||
- geerlingguy.postgresql
|
||||
- ansible
|
||||
- geerlingguy.nginx
|
||||
|
||||
4. Create ``ansible/vars.yml`` to configure your ansible deployment:
|
||||
|
||||
.. code:: yaml
|
||||
|
||||
paperlessng_secret_key: PleaseGenerateAStrongKeyForThis
|
||||
|
||||
paperlessng_superuser_name: YourUserName
|
||||
paperlessng_superuser_email: name@domain.tld
|
||||
paperlessng_superuser_password: YourDesiredPasswordUsedForFirstLogin
|
||||
|
||||
paperlessng_ocr_languages:
|
||||
- eng
|
||||
- deu
|
||||
|
||||
For all of the available options, please check ``ansible/README.md`` and :ref:`configuration`.
|
||||
|
||||
Optional configurations for the above-mentioned PostgreSQL and nginx roles would also go here.
|
||||
|
||||
5. Run the ansible playbook from the management node:
|
||||
|
||||
.. code:: sh
|
||||
|
||||
ansible-playbook playbook.yml
|
||||
|
||||
When this step completes successfully, paperless-ng will be available on the target host at ``http://127.0.0.1:8000`` (or the address you configured).
|
||||
|
||||
Migration to paperless-ng
|
||||
#########################
|
||||
|
||||
At its core, paperless-ng 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. The important things to keep in mind are as follows.
|
||||
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 :ref:`changelog <paperless_changelog>` and take note of breaking changes.
|
||||
* It is recommended to use postgresql as the database now. The docker-compose
|
||||
deployment will automatically create a postgresql instance and instruct
|
||||
paperless to use it. This means that if you use the docker-compose script
|
||||
with your current paperless media and data volumes and used the default
|
||||
sqlite database, **it will not use your sqlite database and it may seem
|
||||
as if your documents are gone**. You may use the provided
|
||||
``docker-compose.sqlite.yml`` script instead, which does not use postgresql. See
|
||||
:ref:`setup-sqlite_to_psql` for details on how to move your data from
|
||||
sqlite to postgres.
|
||||
* 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.
|
||||
@@ -226,35 +592,251 @@ Migration to paperless-ng is then performed in a few simple steps:
|
||||
paperless.
|
||||
|
||||
3. Download the latest release of paperless-ng. You can either go with the
|
||||
docker-compose files or use the archive to build the image yourself.
|
||||
docker-compose files from `here <https://github.com/jonaswinkler/paperless-ng/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-ng
|
||||
in a different location. Paperless-ng will use the same docker volumes
|
||||
as paperless.
|
||||
in a different location.
|
||||
|
||||
4. Adjust ``docker-compose.yml`` and
|
||||
``docker-compose.env`` to your needs.
|
||||
See `docker route`_ for details on which edits are required.
|
||||
.. caution::
|
||||
|
||||
5. Update paperless. See :ref:`administration-updating` for details.
|
||||
Paperless-ng 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-ng. However, if you experience that paperless-ng
|
||||
is not using your old paperless volumes, verify the names of your volumes with
|
||||
|
||||
6. Start paperless-ng.
|
||||
.. 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-ng.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ docker-compose up -d
|
||||
|
||||
7. Paperless installed a permanent redirect to ``admin/`` in your browser. This
|
||||
redirect is still in place and prevents access to the new UI. Clear
|
||||
everything related to paperless in your browsers data in order to fix
|
||||
this issue.
|
||||
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 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::
|
||||
|
||||
TBD.
|
||||
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-ng 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-ng 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-ng 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 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.
|
||||
* Set ``PAPERLESS_OPTIMIZE_THUMBNAILS`` to 'false' if you want faster consumption
|
||||
times. Thumbnails will be about 20% larger.
|
||||
* If using docker, consider setting ``PAPERLESS_WEBSERVER_WORKERS`` to
|
||||
1. This will save some memory.
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Also read `this <https://channels.readthedocs.io/en/stable/deploying.html#nginx-supervisor-ubuntu>`__, towards the end of the section.
|
||||
|
@@ -29,75 +29,182 @@ Check for the following issues:
|
||||
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, check out
|
||||
the configuration file and enable filesystem polling with the setting
|
||||
``PAPERLESS_CONSUMER_POLLING``.
|
||||
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.
|
||||
|
||||
|
||||
Consumer warns ``OCR for XX failed``
|
||||
Paperless always redirects to /admin
|
||||
####################################
|
||||
|
||||
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 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
|
||||
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
|
||||
#######################
|
||||
|
||||
Consumer dies with ``convert: unable to extent pixel cache``
|
||||
############################################################
|
||||
You might see errors such as:
|
||||
|
||||
During the consumption process, Paperless invokes ImageMagick's ``convert``
|
||||
program to translate the source document into something that the OCR engine can
|
||||
understand and this can burn a Very Large amount of memory if the original
|
||||
document is rather long. Similarly, if your system doesn't have a lot of
|
||||
memory to begin with (ie. a Raspberry Pi), then this can happen for even
|
||||
medium-sized documents.
|
||||
.. code:: shell-session
|
||||
|
||||
The solution is to tell ImageMagick *not* to Use All The RAM, as is its
|
||||
default, and instead tell it to used a fixed amount. ``convert`` will then
|
||||
break up the job into hundreds of individual files and use them to slowly
|
||||
compile the finished image. Simply set ``PAPERLESS_CONVERT_MEMORY_LIMIT`` in
|
||||
``/etc/paperless.conf`` to something like ``32000000`` and you'll limit
|
||||
``convert`` to 32MB. Fiddle with this value as you like.
|
||||
chown: changing ownership of '../export': Operation not permitted
|
||||
|
||||
**HOWEVER**: Simply setting this value may not be enough on system where
|
||||
``/tmp`` is mounted as tmpfs, as this is where ``convert`` will write its
|
||||
temporary files. In these cases (most Systemd machines), you need to tell
|
||||
ImageMagick to use a different space for its scratch work. You do this by
|
||||
setting ``PAPERLESS_CONVERT_TMPDIR`` in ``/etc/paperless.conf`` to somewhere
|
||||
that's actually on a physical disk (and writable by the user running
|
||||
Paperless), like ``/var/tmp/paperless`` or ``/home/my_user/tmp`` in a pinch.
|
||||
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.
|
||||
|
||||
|
||||
DecompressionBombWarning and/or no text in the OCR output
|
||||
#########################################################
|
||||
Classifier error: No training data available
|
||||
############################################
|
||||
|
||||
Some users have had issues using Paperless to consume PDFs that were created
|
||||
by merging Very Large Scanned Images into one PDF. If this happens to you,
|
||||
it's likely because the PDF you've created contains some very large pages
|
||||
(millions of pixels) and the process of converting the PDF to a OCR-friendly
|
||||
image is exploding.
|
||||
This indicates that the Auto matching algorithm found no documents to learn from.
|
||||
This may have two reasons:
|
||||
|
||||
Typically, this happens because the scanned images are created with a high
|
||||
DPI and then rolled into the PDF with an assumed DPI of 72 (the default).
|
||||
The best solution then is to specify the DPI used in the scan in the
|
||||
conversion-to-PDF step. So for example, if you scanned the original image
|
||||
with a DPI of 300, then merging the images into the single PDF with
|
||||
``convert`` should look like this:
|
||||
* 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.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ convert -density 300 *.jpg finished.pdf
|
||||
UserWarning in sklearn on every single document
|
||||
###############################################
|
||||
|
||||
For more information on this and situations like it, you should take a look
|
||||
at `Issue #118`_ as that's where this tip originated.
|
||||
You may encounter warnings like this:
|
||||
|
||||
.. _Issue #118: https://github.com/the-paperless-project/paperless/issues/118
|
||||
.. 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/convert/office
|
||||
|
||||
Gotenberg is a server that converts Office documents into PDF documents and has a default timeout of 10 seconds.
|
||||
When conversion takes longer, Gotenberg raises this error.
|
||||
|
||||
You can increase the timeout by configuring an environment variable for gotenberg (see also `here <https://thecodingmachine.github.io/gotenberg/#environment_variables.default_wait_timeout>`__).
|
||||
If using docker-compose, this is achieved by the following configuration change in the ``docker-compose.yml`` file:
|
||||
|
||||
.. code:: yaml
|
||||
|
||||
gotenberg:
|
||||
image: thecodingmachine/gotenberg
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
DISABLE_GOOGLE_CHROME: 1
|
||||
DEFAULT_WAIT_TIMEOUT: 30
|
||||
|
||||
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.
|
||||
|
@@ -5,13 +5,13 @@ 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
|
||||
provices many utilities for finding and managing your documents.
|
||||
provides many utilities for finding and managing your documents.
|
||||
|
||||
|
||||
Terms and definitions
|
||||
#####################
|
||||
|
||||
Paperless esentially consists of two different parts for managing your
|
||||
Paperless essentially consists of two different parts for managing your
|
||||
documents:
|
||||
|
||||
* The *consumer* watches a specified folder and adds all documents in that
|
||||
@@ -30,12 +30,12 @@ Each document has a couple of fields that you can assign to them:
|
||||
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 demarkate the type of a document such as letter,
|
||||
* 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 intially issued.
|
||||
* 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
|
||||
@@ -57,8 +57,29 @@ Adding documents to paperless
|
||||
#############################
|
||||
|
||||
Once you've got Paperless setup, you need to start feeding documents into it.
|
||||
Currently, there are three options: the consumption directory, IMAP (email), and
|
||||
HTTP POST.
|
||||
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 archiveable 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
|
||||
@@ -82,6 +103,26 @@ files from the scanner. Typically, you're looking at an FTP server like
|
||||
|
||||
.. TODO: hyperref to configuration of the location of this magic folder.
|
||||
|
||||
Dashboard 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.
|
||||
|
||||
|
||||
.. _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)
|
||||
============
|
||||
@@ -130,9 +171,14 @@ These are as follows:
|
||||
|
||||
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 acion "mark as read" is
|
||||
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::
|
||||
|
||||
Paperless will process the rules in the order defined in the admin page.
|
||||
@@ -150,6 +196,119 @@ 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.
|
||||
|
||||
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:
|
||||
|
||||
@@ -176,7 +335,7 @@ Processing of the physical documents
|
||||
====================================
|
||||
|
||||
Keep a physical inbox. Whenever you receive a document that you need to
|
||||
archive, put it into your inbox. Regulary, do the following for all documents
|
||||
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
|
||||
@@ -211,18 +370,24 @@ 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 isnt strictly necessary but helps in finding a document when you need
|
||||
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 isnt strictly necessary but helps in finding a document when you need
|
||||
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 corrent. Paperless tries to read
|
||||
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
|
||||
===============
|
||||
|
@@ -1,21 +1,9 @@
|
||||
bind = '127.0.0.1:8000'
|
||||
backlog = 2048
|
||||
workers = 3
|
||||
worker_class = 'sync'
|
||||
worker_connections = 1000
|
||||
timeout = 20
|
||||
keepalive = 2
|
||||
spew = False
|
||||
daemon = False
|
||||
pidfile = None
|
||||
umask = 0
|
||||
user = None
|
||||
group = None
|
||||
tmp_upload_dir = None
|
||||
loglevel = 'info'
|
||||
errorlog = '-'
|
||||
accesslog = '-'
|
||||
proc_name = None
|
||||
import os
|
||||
|
||||
bind = '0.0.0.0:8000'
|
||||
workers = int(os.getenv("PAPERLESS_WEBSERVER_WORKERS", 2))
|
||||
worker_class = 'uvicorn.workers.UvicornWorker'
|
||||
timeout = 120
|
||||
|
||||
def pre_fork(server, worker):
|
||||
pass
|
295
install-paperless-ng.sh
Executable file
@@ -0,0 +1,295 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
ask() {
|
||||
while true ; do
|
||||
if [[ -z $3 ]] ; then
|
||||
read -p "$1 [$2]: " result
|
||||
else
|
||||
read -p "$1 ($3) [$2]: " result
|
||||
fi
|
||||
if [[ -z $result ]]; then
|
||||
ask_result=$2
|
||||
return
|
||||
fi
|
||||
array=$3
|
||||
if [[ -z $3 || " ${array[@]} " =~ " ${result} " ]]; then
|
||||
ask_result=$result
|
||||
return
|
||||
else
|
||||
echo "Invalid option: $result"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
ask_docker_folder() {
|
||||
while true ; do
|
||||
|
||||
read -p "$1 [$2]: " result
|
||||
|
||||
if [[ -z $result ]]; then
|
||||
ask_result=$2
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ $result == /* || $result == ./* ]]; then
|
||||
ask_result=$result
|
||||
return
|
||||
else
|
||||
echo "Invalid folder: $result"
|
||||
fi
|
||||
|
||||
|
||||
done
|
||||
}
|
||||
|
||||
if [[ $(id -u) == "0" ]] ; then
|
||||
echo "Do not run this script as root."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z $(which wget) ]] ; then
|
||||
echo "wget executable not found. Is wget installed?"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z $(which docker) ]] ; then
|
||||
echo "docker executable not found. Is docker installed?"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z $(which docker-compose) ]] ; then
|
||||
echo "docker-compose executable not found. Is docker-compose installed?"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "############################################"
|
||||
echo "### Paperless-ng docker installation ###"
|
||||
echo "############################################"
|
||||
echo ""
|
||||
echo "This script will download, configure and start paperless-ng."
|
||||
|
||||
echo ""
|
||||
echo "1. Folder configuration"
|
||||
echo "======================="
|
||||
echo ""
|
||||
echo "The target folder is used to store the configuration files of "
|
||||
echo "paperless. You can move this folder around after installing paperless."
|
||||
echo "You will need this folder whenever you want to start, stop, update or "
|
||||
echo "maintain your paperless instance."
|
||||
echo ""
|
||||
|
||||
ask "Target folder" "$(pwd)/paperless-ng"
|
||||
TARGET_FOLDER=$ask_result
|
||||
|
||||
echo ""
|
||||
echo "The consume folder is where paperles will search for new documents."
|
||||
echo "Point this to a folder where your scanner is able to put your scanned"
|
||||
echo "documents."
|
||||
echo ""
|
||||
echo "CAUTION: You must specify an absolute path starting with / or a relative "
|
||||
echo "path starting with ./ here. Examples:"
|
||||
echo " /mnt/consume"
|
||||
echo " ./consume"
|
||||
echo ""
|
||||
|
||||
ask_docker_folder "Consume folder" "$TARGET_FOLDER/consume"
|
||||
CONSUME_FOLDER=$ask_result
|
||||
|
||||
echo ""
|
||||
echo "The media folder is where paperless stores your documents."
|
||||
echo "Leave empty and docker will manage this folder for you."
|
||||
echo "Docker usually stores managed folders in /var/lib/docker/volumes."
|
||||
echo ""
|
||||
echo "CAUTION: If specified, you must specify an absolute path starting with /"
|
||||
echo "or a relative path starting with ./ here."
|
||||
echo ""
|
||||
|
||||
ask_docker_folder "Media folder" ""
|
||||
MEDIA_FOLDER=$ask_result
|
||||
|
||||
echo ""
|
||||
echo "The data folder is where paperless stores other data, such as your"
|
||||
echo "SQLite database (if used), the search index and other data."
|
||||
echo "As with the media folder, leave empty to have this managed by docker."
|
||||
echo ""
|
||||
echo "CAUTION: If specified, you must specify an absolute path starting with /"
|
||||
echo "or a relative path starting with ./ here."
|
||||
echo ""
|
||||
|
||||
ask_docker_folder "Data folder" ""
|
||||
DATA_FOLDER=$ask_result
|
||||
|
||||
echo ""
|
||||
echo "2. Application configuration"
|
||||
echo "============================"
|
||||
|
||||
echo ""
|
||||
echo "The port on which the paperless webserver will listen for incoming"
|
||||
echo "connections."
|
||||
echo ""
|
||||
|
||||
ask "Port" "8000"
|
||||
PORT=$ask_result
|
||||
|
||||
echo ""
|
||||
echo "Database backend: PostgreSQL and SQLite are available. Use PostgreSQL"
|
||||
echo "if unsure. If you're running on a low-power device such as Raspberry"
|
||||
echo "Pi, use SQLite to save resources."
|
||||
echo ""
|
||||
|
||||
ask "Database backend" "postgres" "postgres sqlite"
|
||||
DATABASE_BACKEND=$ask_result
|
||||
|
||||
echo ""
|
||||
echo "Paperless is able to use Apache Tika to support Office documents such as"
|
||||
echo "Word, Excel, Powerpoint, and Libreoffice equivalents. This feature"
|
||||
echo "requires more resources due to the required services."
|
||||
echo ""
|
||||
|
||||
ask "Enable Apache Tika?" "no" "yes no"
|
||||
TIKA_ENABLED=$ask_result
|
||||
|
||||
echo ""
|
||||
echo "Specify the default language that most of your documents are written in."
|
||||
echo "Use ISO 639-2, (T) variant language codes: "
|
||||
echo "https://www.loc.gov/standards/iso639-2/php/code_list.php"
|
||||
echo "Common values: eng (English) deu (German) nld (Dutch) fra (French)"
|
||||
echo ""
|
||||
|
||||
ask "OCR language" "eng"
|
||||
OCR_LANGUAGE=$ask_result
|
||||
|
||||
echo ""
|
||||
echo "Specify the user id and group id you wish to run paperless as."
|
||||
echo "Paperless will also change ownership on the data, media and consume"
|
||||
echo "folder to the specified values, so it's a good idea to supply the user id"
|
||||
echo "and group id of your unix user account."
|
||||
echo "If unsure, leave default."
|
||||
echo ""
|
||||
|
||||
ask "User ID" "$(id -u)"
|
||||
USERMAP_UID=$ask_result
|
||||
|
||||
ask "Group ID" "$(id -g)"
|
||||
USERMAP_GID=$ask_result
|
||||
|
||||
echo ""
|
||||
echo "3. Login credentials"
|
||||
echo "===================="
|
||||
echo ""
|
||||
echo "Specify initial login credentials. You can change these later."
|
||||
echo "A mail address is required, however it is not used in paperless. You don't"
|
||||
echo "need to provide an actual mail address."
|
||||
echo ""
|
||||
|
||||
ask "Paperless username" "$(whoami)"
|
||||
USERNAME=$ask_result
|
||||
|
||||
while true; do
|
||||
read -sp "Paperless password: " PASSWORD
|
||||
echo ""
|
||||
|
||||
if [[ -z $PASSWORD ]] ; then
|
||||
echo "Password cannot be empty."
|
||||
continue
|
||||
fi
|
||||
|
||||
read -sp "Paperless password (again): " PASSWORD_REPEAT
|
||||
echo ""
|
||||
|
||||
if [[ ! "$PASSWORD" == "$PASSWORD_REPEAT" ]] ; then
|
||||
echo "Passwords did not match"
|
||||
else
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
ask "Email" "$USERNAME@localhost"
|
||||
EMAIL=$ask_result
|
||||
|
||||
echo ""
|
||||
echo "Summary"
|
||||
echo "======="
|
||||
echo ""
|
||||
|
||||
echo "Target folder: $TARGET_FOLDER"
|
||||
echo "Consume folder: $CONSUME_FOLDER"
|
||||
if [[ -z $MEDIA_FOLDER ]] ; then
|
||||
echo "Media folder: Managed by docker"
|
||||
else
|
||||
echo "Media folder: $MEDIA_FOLDER"
|
||||
fi
|
||||
if [[ -z $DATA_FOLDER ]] ; then
|
||||
echo "Data folder: Managed by docker"
|
||||
else
|
||||
echo "Data folder: $DATA_FOLDER"
|
||||
fi
|
||||
echo ""
|
||||
echo "Port: $PORT"
|
||||
echo "Database: $DATABASE_BACKEND"
|
||||
echo "Tika enabled: $TIKA_ENABLED"
|
||||
echo "OCR language: $OCR_LANGUAGE"
|
||||
echo "User id: $USERMAP_UID"
|
||||
echo "Group id: $USERMAP_GID"
|
||||
echo ""
|
||||
echo "Paperless username: $USERNAME"
|
||||
echo "Paperless email: $EMAIL"
|
||||
|
||||
echo ""
|
||||
read -p "Press any key to install."
|
||||
|
||||
echo ""
|
||||
echo "Installing paperless..."
|
||||
echo ""
|
||||
|
||||
mkdir -p "$TARGET_FOLDER"
|
||||
|
||||
cd "$TARGET_FOLDER"
|
||||
|
||||
DOCKER_COMPOSE_VERSION=$DATABASE_BACKEND
|
||||
|
||||
if [[ $TIKA_ENABLED == "yes" ]] ; then
|
||||
DOCKER_COMPOSE_VERSION="$DOCKER_COMPOSE_VERSION-tika"
|
||||
fi
|
||||
|
||||
wget "https://raw.githubusercontent.com/jonaswinkler/paperless-ng/master/docker/compose/docker-compose.$DOCKER_COMPOSE_VERSION.yml" -O docker-compose.yml
|
||||
wget "https://raw.githubusercontent.com/jonaswinkler/paperless-ng/master/docker/compose/.env" -O .env
|
||||
|
||||
SECRET_KEY=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 64 | head -n 1)
|
||||
|
||||
DEFAULT_LANGUAGES="deu eng fra ita spa"
|
||||
|
||||
{
|
||||
if [[ ! $USERMAP_UID == "1000" ]] ; then
|
||||
echo "USERMAP_UID=$USERMAP_UID"
|
||||
fi
|
||||
if [[ ! $USERMAP_GID == "1000" ]] ; then
|
||||
echo "USERMAP_GID=$USERMAP_GID"
|
||||
fi
|
||||
echo "PAPERLESS_OCR_LANGUAGE=$OCR_LANGUAGE"
|
||||
echo "PAPERLESS_SECRET_KEY=$SECRET_KEY"
|
||||
if [[ ! " ${DEFAULT_LANGUAGES[@]} " =~ " ${OCR_LANGUAGE} " ]] ; then
|
||||
echo "PAPERLESS_OCR_LANGUAGES=$OCR_LANGUAGE"
|
||||
fi
|
||||
} > docker-compose.env
|
||||
|
||||
sed -i "s/- 8000:8000/- $PORT:8000/g" docker-compose.yml
|
||||
|
||||
sed -i "s#- \./consume:/usr/src/paperless/consume#- $CONSUME_FOLDER:/usr/src/paperless/consume#g" docker-compose.yml
|
||||
|
||||
if [[ -n $MEDIA_FOLDER ]] ; then
|
||||
sed -i "s#- media:/usr/src/paperless/media#- $MEDIA_FOLDER:/usr/src/paperless/media#g" docker-compose.yml
|
||||
fi
|
||||
|
||||
if [[ -n $DATA_FOLDER ]] ; then
|
||||
sed -i "s#- data:/usr/src/paperless/data#- $DATA_FOLDER:/usr/src/paperless/data#g" docker-compose.yml
|
||||
fi
|
||||
|
||||
docker-compose pull
|
||||
|
||||
docker-compose run --rm -e DJANGO_SUPERUSER_PASSWORD="$PASSWORD" webserver createsuperuser --noinput --username "$USERNAME" --email "$EMAIL"
|
||||
|
||||
docker-compose up -d
|
@@ -1,287 +1,78 @@
|
||||
# Sample paperless.conf
|
||||
# Copy this file to /etc/paperless.conf and modify it to suit your needs.
|
||||
# As this file contains passwords it should only be readable by the user
|
||||
# running paperless.
|
||||
# Have a look at the docs for documentation.
|
||||
# https://paperless-ng.readthedocs.io/en/latest/configuration.html
|
||||
|
||||
###############################################################################
|
||||
#### Message Broker ####
|
||||
###############################################################################
|
||||
# Debug. Only enable this for development.
|
||||
|
||||
#PAPERLESS_DEBUG=false
|
||||
|
||||
# Required services
|
||||
|
||||
# This is required for processing scheduled tasks such as email fetching, index
|
||||
# optimization and for training the automatic document matcher.
|
||||
# Defaults to localhost:6379.
|
||||
#PAPERLESS_REDIS=redis://localhost:6379
|
||||
|
||||
|
||||
###############################################################################
|
||||
#### Database Settings ####
|
||||
###############################################################################
|
||||
|
||||
# By default, sqlite is used as the database backend. This can be changed here.
|
||||
# The docker-compose service definition uses a postgresql server. The
|
||||
# configuration for this is already done inside the docker-compose.env file.
|
||||
|
||||
#Set PAPERLESS_DBHOST and postgresql will be used instead of mysql.
|
||||
#PAPERLESS_DBHOST=localhost
|
||||
|
||||
#Adjust port if necessary
|
||||
#PAPERLESS_DBPORT=
|
||||
|
||||
#name, user and pass all default to "paperless"
|
||||
#PAPERLESS_DBPORT=5432
|
||||
#PAPERLESS_DBNAME=paperless
|
||||
#PAPERLESS_DBUSER=paperless
|
||||
#PAPERLESS_DBPASS=paperless
|
||||
#PAPERLESS_DBSSLMODE=prefer
|
||||
|
||||
# Paths and folders
|
||||
|
||||
###############################################################################
|
||||
#### Paths & Folders ####
|
||||
###############################################################################
|
||||
|
||||
# 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.
|
||||
PAPERLESS_CONSUMPTION_DIR=../consume
|
||||
|
||||
# This is where paperless stores all its data (search index, sqlite database,
|
||||
# classification model, etc).
|
||||
#PAPERLESS_CONSUMPTION_DIR=../consume
|
||||
#PAPERLESS_DATA_DIR=../data
|
||||
|
||||
# This is where your documents and thumbnails are stored.
|
||||
#PAPERLESS_MEDIA_ROOT=../media
|
||||
|
||||
# Override the default STATIC_ROOT here. This is where all static files
|
||||
# created using "collectstatic" manager command are stored.
|
||||
#PAPERLESS_STATICDIR=../static
|
||||
|
||||
|
||||
# Override the STATIC_URL here. Unless you're hosting Paperless off a
|
||||
# subdomain like /paperless/, you probably don't need to change this.
|
||||
#PAPERLESS_STATIC_URL=/static/
|
||||
|
||||
|
||||
# Specify a filename format for the document (directories are supported)
|
||||
# Use the following placeholders:
|
||||
# * {correspondent}
|
||||
# * {title}
|
||||
# * {created}
|
||||
# * {added}
|
||||
# * {tags[KEY]} If your tags conform to key_value or key-value
|
||||
# * {tags[INDEX]} If your tags are strings, select the tag by index
|
||||
# Uniqueness of filenames is ensured, as an incrementing counter is attached
|
||||
# to each filename.
|
||||
#PAPERLESS_FILENAME_FORMAT=
|
||||
|
||||
###############################################################################
|
||||
#### Security ####
|
||||
###############################################################################
|
||||
# Security and hosting
|
||||
|
||||
# Controls whether django's debug mode is enabled. Disable this on production
|
||||
# systems. Debug mode is disabled by default.
|
||||
#PAPERLESS_DEBUG=false
|
||||
|
||||
# GnuPG encryption is deprecated and will be removed in future versions.
|
||||
#
|
||||
# Dont use it. It does not provide any security at all.
|
||||
#
|
||||
# Paperless can be instructed to attempt to encrypt your PDF files with GPG
|
||||
# using the PAPERLESS_PASSPHRASE specified below. If however you're not
|
||||
# concerned about encrypting these files (for example if you have disk
|
||||
# encryption locally) then you don't need this and can safely leave this value
|
||||
# un-set.
|
||||
#
|
||||
# One final note about the passphrase. Once you've consumed a document with
|
||||
# one passphrase, DON'T CHANGE IT. Paperless assumes this to be a constant and
|
||||
# can't properly export documents that were encrypted with an old passphrase if
|
||||
# you've since changed it to a new one.
|
||||
#
|
||||
# The default is to not use encryption at all.
|
||||
#PAPERLESS_PASSPHRASE=secret
|
||||
|
||||
|
||||
# The secret key has a default that should be fine so long as you're hosting
|
||||
# Paperless on a closed network. However, if you're putting this anywhere
|
||||
# public, you should change the key to something unique and verbose.
|
||||
#PAPERLESS_SECRET_KEY=change-me
|
||||
|
||||
|
||||
# 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/1.10/topics/security/#host-headers-virtual-hosting
|
||||
#
|
||||
# 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,"
|
||||
#PAPERLESS_ALLOWED_HOSTS=example.com,www.example.com
|
||||
|
||||
# If you decide to use the Paperless API in an ajax call, you need to add your
|
||||
# servers to the list of allowed hosts that can do CORS calls. By default
|
||||
# Paperless allows calls from localhost:8080, but you'd like to change that,
|
||||
# you can set this value to a comma-separated list.
|
||||
#PAPERLESS_CORS_ALLOWED_HOSTS=localhost:8080,example.com,localhost:8000
|
||||
|
||||
# To host paperless under a subpath url like example.com/paperless you set
|
||||
# this value to /paperless. No trailing slash!
|
||||
#
|
||||
# https://docs.djangoproject.com/en/1.11/ref/settings/#force-script-name
|
||||
#PAPERLESS_CORS_ALLOWED_HOSTS=http://example.com,http://localhost:8000
|
||||
#PAPERLESS_FORCE_SCRIPT_NAME=
|
||||
#PAPERLESS_STATIC_URL=/static/
|
||||
#PAPERLESS_AUTO_LOGIN_USERNAME=
|
||||
#PAPERLESS_COOKIE_PREFIX=
|
||||
#PAPERLESS_ENABLE_HTTP_REMOTE_USER=false
|
||||
|
||||
###############################################################################
|
||||
#### Software Tweaks ####
|
||||
###############################################################################
|
||||
# OCR settings
|
||||
|
||||
# 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.
|
||||
#PAPERLESS_TASK_WORKERS=1
|
||||
|
||||
# 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.
|
||||
#PAPERLESS_THREADS_PER_WORKER=1
|
||||
|
||||
# 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, and using as much cores as
|
||||
# possible.
|
||||
# If you only specify PAPERLESS_TASK_WORKERS, paperless will adjust
|
||||
# PAPERLESS_THREADS_PER_WORKER automatically.
|
||||
|
||||
# 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 below, which will then cause paperless
|
||||
# to periodically check your consumption directory for changes.
|
||||
#PAPERLESS_CONSUMER_POLLING=10
|
||||
|
||||
|
||||
# When the consumer detects a duplicate document, it will not touch the
|
||||
# original document. This default behavior can be changed here.
|
||||
#PAPERLESS_CONSUMER_DELETE_DUPLICATES=false
|
||||
|
||||
# Use optipng to optimize thumbnails. This usually reduces the sice of
|
||||
# thumbnails by about 20%, but uses considerable compute time during
|
||||
# consumption.
|
||||
#PAPERLESS_OPTIMIZE_THUMBNAILS=true
|
||||
|
||||
# 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. The default is blank, which means nothing will be executed. For more
|
||||
# information, take a look at the docs:
|
||||
# http://paperless.readthedocs.org/en/latest/consumption.html#hooking-into-the-consumption-process
|
||||
#PAPERLESS_POST_CONSUME_SCRIPT=/path/to/an/arbitrary/script.sh
|
||||
|
||||
# By default, paperless will check the document text for document date information.
|
||||
# Uncomment the line below 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. The filename will be
|
||||
# checked first, and if nothing is found, the document text will be checked
|
||||
# as normal.
|
||||
#PAPERLESS_FILENAME_DATE_ORDER=YMD
|
||||
|
||||
# Sometimes devices won't create filenames which can be parsed properly
|
||||
# by the filename parser (see
|
||||
# https://paperless.readthedocs.io/en/latest/guesswork.html).
|
||||
#
|
||||
# This setting allows to specify a list of transformations
|
||||
# in regular expression syntax, which are passed in order to re.sub.
|
||||
# Transformation stops after the first match, so at most one transformation
|
||||
# is applied.
|
||||
#
|
||||
# Syntax is a JSON array of dictionaries containing "pattern" and "repl"
|
||||
# as keys.
|
||||
#
|
||||
# The example below transforms filenames created by a Brother ADS-2400N
|
||||
# document scanner in its standard configuration `Name_Date_Count', so that
|
||||
# count is used as title, name as tag and date can be parsed by paperless.
|
||||
#PAPERLESS_FILENAME_PARSE_TRANSFORMS=[{"pattern":"^([a-z]+)_(\\d{8})_(\\d{6})_([0-9]+)\\.", "repl":"\\2\\3Z - \\4 - \\1."}]
|
||||
|
||||
#
|
||||
# The following values use sensible defaults for modern systems, but if you're
|
||||
# running Paperless on a low-resource device (like a Raspberry Pi), modifying
|
||||
# some of these values may be necessary.
|
||||
#
|
||||
|
||||
|
||||
# Customize the default language that tesseract will attempt to use when
|
||||
# parsing documents. The default language is used whenever
|
||||
# - No language could be detected on a document
|
||||
# - No tesseract data files are available for the detected language
|
||||
# It should be a 3-letter language code consistent with ISO
|
||||
# 639: https://www.loc.gov/standards/iso639-2/php/code_list.php
|
||||
#PAPERLESS_OCR_LANGUAGE=eng
|
||||
|
||||
|
||||
# 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 32000000. 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 probably search
|
||||
# the web for "MAGICK_MEMORY_LIMIT".
|
||||
#PAPERLESS_OCR_MODE=skip
|
||||
#PAPERLESS_OCR_OUTPUT_TYPE=pdfa
|
||||
#PAPERLESS_OCR_PAGES=1
|
||||
#PAPERLESS_OCR_IMAGE_DPI=300
|
||||
#PAPERLESS_OCR_CLEAN=clean
|
||||
#PAPERLESS_OCR_DESKEW=true
|
||||
#PAPERLESS_OCR_ROTATE_PAGES=true
|
||||
#PAPERLESS_OCR_ROTATE_PAGES_THRESHOLD=12.0
|
||||
#PAPERLESS_OCR_USER_ARGS={}
|
||||
#PAPERLESS_CONVERT_MEMORY_LIMIT=0
|
||||
|
||||
|
||||
# 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 probably search
|
||||
# the web for "MAGICK_TMPDIR".
|
||||
#PAPERLESS_CONVERT_TMPDIR=/var/tmp/paperless
|
||||
|
||||
# Software tweaks
|
||||
|
||||
# By default the conversion density setting for documents is 300DPI, in some
|
||||
# cases it has proven useful to configure a lesser value.
|
||||
# This setting has a high impact on the physical size of tmp page files,
|
||||
# the speed of document conversion, and can affect the accuracy of OCR
|
||||
# results. Individual results can vary and this setting should be tested
|
||||
# thoroughly against the documents you are importing to see if it has any
|
||||
# impacts either negative or positive.
|
||||
# Testing on limited document sets has shown a setting of 200 can cut the
|
||||
# size of tmp files by 1/3, and speed up conversion by up to 4x
|
||||
# with little impact to OCR accuracy.
|
||||
#PAPERLESS_CONVERT_DENSITY=300
|
||||
|
||||
# By default Paperless does not OCR a document if the text can be retrieved from
|
||||
# the document directly. Set to true to always OCR documents.
|
||||
#PAPERLESS_OCR_ALWAYS=false
|
||||
|
||||
|
||||
###############################################################################
|
||||
#### Interface ####
|
||||
###############################################################################
|
||||
|
||||
# Override the default UTC time zone here.
|
||||
# See https://docs.djangoproject.com/en/1.10/ref/settings/#std:setting-TIME_ZONE
|
||||
# for details on how to set it.
|
||||
#PAPERLESS_TASK_WORKERS=1
|
||||
#PAPERLESS_THREADS_PER_WORKER=1
|
||||
#PAPERLESS_TIME_ZONE=UTC
|
||||
#PAPERLESS_CONSUMER_POLLING=10
|
||||
#PAPERLESS_CONSUMER_DELETE_DUPLICATES=false
|
||||
#PAPERLESS_CONSUMER_RECURSIVE=false
|
||||
#PAPERLESS_CONSUMER_SUBDIRS_AS_TAGS=false
|
||||
#PAPERLESS_OPTIMIZE_THUMBNAILS=true
|
||||
#PAPERLESS_POST_CONSUME_SCRIPT=/path/to/an/arbitrary/script.sh
|
||||
#PAPERLESS_FILENAME_DATE_ORDER=YMD
|
||||
#PAPERLESS_FILENAME_PARSE_TRANSFORMS=[]
|
||||
#PAPERLESS_THUMBNAIL_FONT_NAME=
|
||||
#PAPERLESS_IGNORE_DATES=
|
||||
|
||||
# Tika settings
|
||||
|
||||
###############################################################################
|
||||
#### Third-Party Binaries ####
|
||||
###############################################################################
|
||||
#PAPERLESS_TIKA_ENABLED=false
|
||||
#PAPERLESS_TIKA_ENDPOINT=http://localhost:9998
|
||||
#PAPERLESS_TIKA_GOTENBERG_ENDPOINT=http://localhost:3000
|
||||
|
||||
# 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 here.
|
||||
# Binaries
|
||||
|
||||
# Convert (part of the ImageMagick suite)
|
||||
#PAPERLESS_CONVERT_BINARY=/usr/bin/convert
|
||||
|
||||
# Ghostscript
|
||||
#PAPERLESS_GS_BINARY=/usr/bin/gs
|
||||
|
||||
# Unpaper
|
||||
#PAPERLESS_UNPAPER_BINARY=/usr/bin/unpaper
|
||||
|
||||
# Optipng (for optimising thumbnail sizes)
|
||||
#PAPERLESS_OPTIPNG_BINARY=/usr/bin/optipng
|
||||
|
101
requirements.txt
Normal file
@@ -0,0 +1,101 @@
|
||||
#
|
||||
# These requirements were autogenerated by pipenv
|
||||
# To regenerate from the project's Pipfile, run:
|
||||
#
|
||||
# pipenv lock --requirements
|
||||
#
|
||||
|
||||
-i https://pypi.python.org/simple
|
||||
--extra-index-url https://www.piwheels.org/simple
|
||||
aioredis==1.3.1
|
||||
arrow==0.17.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
|
||||
asgiref==3.3.1; python_version >= '3.5'
|
||||
async-timeout==3.0.1; python_full_version >= '3.5.3'
|
||||
attrs==20.3.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
|
||||
autobahn==21.2.1; python_version >= '3.6'
|
||||
automat==20.2.0
|
||||
blessed==1.17.12
|
||||
certifi==2020.12.5
|
||||
cffi==1.14.5
|
||||
channels-redis==3.2.0
|
||||
channels==3.0.3
|
||||
chardet==4.0.0; python_version >= '3.1'
|
||||
click==7.1.2; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
|
||||
coloredlogs==15.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
|
||||
concurrent-log-handler==0.9.19
|
||||
constantly==15.1.0
|
||||
cryptography==3.3.2
|
||||
daphne==3.0.1; python_version >= '3.6'
|
||||
dateparser==0.7.6
|
||||
django-cors-headers==3.7.0
|
||||
django-extensions==3.1.1
|
||||
django-filter==2.4.0
|
||||
django-picklefield==3.0.1; python_version >= '3'
|
||||
django-q==1.3.4
|
||||
django==3.1.7
|
||||
djangorestframework==3.12.2
|
||||
filelock==3.0.12
|
||||
fuzzywuzzy[speedup]==0.18.0
|
||||
gunicorn==20.0.4
|
||||
h11==0.12.0; python_version >= '3.6'
|
||||
hiredis==1.1.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
|
||||
httptools==0.1.1
|
||||
humanfriendly==9.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
|
||||
hyperlink==21.0.0
|
||||
idna==2.10; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
|
||||
imap-tools==0.37.0
|
||||
img2pdf==0.4.0
|
||||
incremental==17.5.0
|
||||
inotify-simple==1.3.5; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
|
||||
inotifyrecursive==0.3.5
|
||||
joblib==1.0.1; python_version >= '3.6'
|
||||
langdetect==1.0.8
|
||||
lxml==4.6.2; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
|
||||
msgpack==1.0.2
|
||||
numpy==1.19.5
|
||||
ocrmypdf==11.6.2
|
||||
pathvalidate==2.3.2
|
||||
pdfminer.six==20201018
|
||||
pikepdf==2.5.2
|
||||
pillow==8.1.0
|
||||
pluggy==0.13.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
|
||||
portalocker==2.2.1; python_version >= '3'
|
||||
psycopg2-binary==2.8.6
|
||||
pyasn1-modules==0.2.8
|
||||
pyasn1==0.4.8
|
||||
pycparser==2.20; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
|
||||
pyhamcrest==2.0.2; python_version >= '3.5'
|
||||
pyopenssl==20.0.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
|
||||
python-dateutil==2.8.1
|
||||
python-dotenv==0.15.0
|
||||
python-gnupg==0.4.6
|
||||
python-levenshtein==0.12.2
|
||||
python-magic==0.4.22
|
||||
pytz==2021.1
|
||||
pyyaml==5.4.1
|
||||
redis==3.5.3
|
||||
regex==2020.11.13
|
||||
reportlab==3.5.59
|
||||
requests==2.25.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
|
||||
scikit-learn==0.24.0
|
||||
scipy==1.5.4
|
||||
service-identity==18.1.0
|
||||
six==1.15.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
|
||||
sortedcontainers==2.3.0
|
||||
sqlparse==0.4.1; python_version >= '3.5'
|
||||
threadpoolctl==2.1.0; python_version >= '3.5'
|
||||
tika==1.24
|
||||
tqdm==4.57.0
|
||||
twisted[tls]==20.3.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
|
||||
txaio==21.2.1; python_version >= '3.6'
|
||||
tzlocal==2.1
|
||||
urllib3==1.26.3; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'
|
||||
uvicorn[standard]==0.13.4
|
||||
uvloop==0.14.0
|
||||
watchdog==1.0.2
|
||||
watchgod==0.7
|
||||
wcwidth==0.2.5
|
||||
websockets==8.1
|
||||
whitenoise==5.2.0
|
||||
whoosh==2.7.4
|
||||
zope.interface==5.2.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
|
16
resources/logo.txt
Normal file
@@ -0,0 +1,16 @@
|
||||
9w
|
||||
{@@N
|
||||
Q@@@@H
|
||||
G@@@@@@@\
|
||||
SilN@@@@@@@
|
||||
*Q *@@@@@@@@S /= = = = = = = = = = = = = = = = = =\
|
||||
*@ B@@@@@@@@N || ||
|
||||
N R$ A@@@@@@@@@@ || PAPERLESS-NG ||
|
||||
x@@ $U B@@@@@@@@@R || ||
|
||||
N@@N^ @ N@@@@@@@@@* \= = = = = = = = = = = = = = = = = =/
|
||||
|@@@u @ E@@@@@@@@l
|
||||
Q@@@ \ Px@@@@@@P
|
||||
1@@S` @@@o'
|
||||
z$ ;
|
||||
v
|
||||
/
|
@@ -1,100 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
|
||||
VERSION=$1
|
||||
|
||||
if [ -z "$VERSION" ]
|
||||
then
|
||||
echo "Need a version string."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# source root directory of paperless
|
||||
PAPERLESS_ROOT=$(git rev-parse --show-toplevel)
|
||||
|
||||
# output directory
|
||||
PAPERLESS_DIST="$PAPERLESS_ROOT/dist"
|
||||
PAPERLESS_DIST_APP="$PAPERLESS_DIST/paperless-ng"
|
||||
|
||||
if [ -d "$PAPERLESS_DIST" ]
|
||||
then
|
||||
echo "Removing $PAPERLESS_DIST"
|
||||
rm "$PAPERLESS_DIST" -r
|
||||
fi
|
||||
|
||||
mkdir "$PAPERLESS_DIST"
|
||||
mkdir "$PAPERLESS_DIST_APP"
|
||||
mkdir "$PAPERLESS_DIST_APP/docker"
|
||||
|
||||
# setup dependencies.
|
||||
|
||||
cd "$PAPERLESS_ROOT"
|
||||
|
||||
pipenv clean
|
||||
pipenv install --dev
|
||||
pipenv lock --keep-outdated -r > "$PAPERLESS_DIST_APP/requirements.txt"
|
||||
|
||||
# test if the application works.
|
||||
|
||||
cd "$PAPERLESS_ROOT/src"
|
||||
pipenv run pytest --cov
|
||||
pipenv run pycodestyle
|
||||
|
||||
# make the documentation.
|
||||
|
||||
cd "$PAPERLESS_ROOT/docs"
|
||||
make clean html
|
||||
|
||||
# copy stuff into place
|
||||
|
||||
# the application itself
|
||||
|
||||
cp "$PAPERLESS_ROOT/.env" \
|
||||
"$PAPERLESS_ROOT/.dockerignore" \
|
||||
"$PAPERLESS_ROOT/CONTRIBUTING.md" \
|
||||
"$PAPERLESS_ROOT/LICENSE" \
|
||||
"$PAPERLESS_ROOT/Pipfile" \
|
||||
"$PAPERLESS_ROOT/Pipfile.lock" \
|
||||
"$PAPERLESS_ROOT/README.md" "$PAPERLESS_DIST_APP"
|
||||
|
||||
cp "$PAPERLESS_ROOT/paperless.conf.example" "$PAPERLESS_DIST_APP/paperless.conf"
|
||||
|
||||
# copy python source, templates and static files.
|
||||
cd "$PAPERLESS_ROOT"
|
||||
find src -wholename '*/templates/*' -o -wholename '*/static/*' -o -name '*.py' | cpio -pdm "$PAPERLESS_DIST_APP"
|
||||
|
||||
# build the front end.
|
||||
|
||||
cd "$PAPERLESS_ROOT/src-ui"
|
||||
ng build --prod --output-hashing none --sourceMap=false --output-path "$PAPERLESS_DIST_APP/src/documents/static/frontend"
|
||||
|
||||
# documentation
|
||||
cp "$PAPERLESS_ROOT/docs/_build/html/" "$PAPERLESS_DIST_APP/docs" -r
|
||||
|
||||
# docker files for building the image yourself
|
||||
cp "$PAPERLESS_ROOT/docker/local/"* "$PAPERLESS_DIST_APP"
|
||||
cp "$PAPERLESS_ROOT/docker/docker-compose.env" "$PAPERLESS_DIST_APP"
|
||||
|
||||
# docker files for pulling from docker hub
|
||||
cp "$PAPERLESS_ROOT/docker/hub/"* "$PAPERLESS_DIST"
|
||||
cp "$PAPERLESS_ROOT/docker/docker-compose.env" "$PAPERLESS_DIST"
|
||||
|
||||
# auxiliary files required for the docker image
|
||||
cp "$PAPERLESS_ROOT/docker/docker-entrypoint.sh" "$PAPERLESS_DIST_APP/docker/"
|
||||
cp "$PAPERLESS_ROOT/docker/gunicorn.conf.py" "$PAPERLESS_DIST_APP/docker/"
|
||||
cp "$PAPERLESS_ROOT/docker/imagemagick-policy.xml" "$PAPERLESS_DIST_APP/docker/"
|
||||
cp "$PAPERLESS_ROOT/docker/supervisord.conf" "$PAPERLESS_DIST_APP/docker/"
|
||||
|
||||
# try to make the docker build.
|
||||
|
||||
cd "$PAPERLESS_DIST_APP"
|
||||
|
||||
docker build . -t "jonaswinkler/paperless-ng:$VERSION"
|
||||
|
||||
# works. package the app!
|
||||
|
||||
cd "$PAPERLESS_DIST"
|
||||
|
||||
tar -cJf "paperless-ng-$VERSION.tar.xz" paperless-ng/
|
@@ -1,10 +1,12 @@
|
||||
[Unit]
|
||||
Description=Paperless consumer
|
||||
Requires=redis.service
|
||||
|
||||
[Service]
|
||||
User=paperless
|
||||
Group=paperless
|
||||
ExecStart=/home/paperless/project/virtualenv/bin/python /home/paperless/project/src/manage.py document_consumer
|
||||
WorkingDirectory=/opt/paperless/src
|
||||
ExecStart=python3 manage.py document_consumer
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
12
scripts/paperless-scheduler.service
Normal file
@@ -0,0 +1,12 @@
|
||||
[Unit]
|
||||
Description=Paperless consumer
|
||||
Requires=redis.service
|
||||
|
||||
[Service]
|
||||
User=paperless
|
||||
Group=paperless
|
||||
WorkingDirectory=/opt/paperless/src
|
||||
ExecStart=python3 manage.py qcluster
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
@@ -2,11 +2,13 @@
|
||||
Description=Paperless webserver
|
||||
After=network.target
|
||||
Wants=network.target
|
||||
Requires=redis.service
|
||||
|
||||
[Service]
|
||||
User=paperless
|
||||
Group=paperless
|
||||
ExecStart=/home/paperless/project/virtualenv/bin/gunicorn --pythonpath=/home/paperless/project/src paperless.wsgi -w 2
|
||||
WorkingDirectory=/opt/paperless/src
|
||||
ExecStart=/opt/paperless/.local/bin/gunicorn -c /opt/paperless/gunicorn.conf.py paperless.asgi:application
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
@@ -1,23 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
|
||||
VERSION=$1
|
||||
|
||||
if [ -z "$VERSION" ]
|
||||
then
|
||||
echo "Need a version string."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# source root directory of paperless
|
||||
PAPERLESS_ROOT=$(git rev-parse --show-toplevel)
|
||||
|
||||
# output directory
|
||||
PAPERLESS_DIST="$PAPERLESS_ROOT/dist"
|
||||
PAPERLESS_DIST_APP="$PAPERLESS_DIST/paperless-ng"
|
||||
|
||||
cd "$PAPERLESS_DIST_APP"
|
||||
|
||||
docker push "jonaswinkler/paperless-ng:$VERSION"
|
@@ -1,2 +1,4 @@
|
||||
docker run -p 5432:5432 -v paperless_pgdata:/var/lib/postgresql/data -d postgres:13
|
||||
docker run -d -p 6379:6379 redis:latest
|
||||
docker run -p 3000:3000 -d thecodingmachine/gotenberg
|
||||
docker run -p 9998:9998 -d apache/tika
|
||||
|
@@ -1,126 +1,153 @@
|
||||
{
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"version": 1,
|
||||
"newProjectRoot": "projects",
|
||||
"projects": {
|
||||
"paperless-ui": {
|
||||
"projectType": "application",
|
||||
"schematics": {},
|
||||
"root": "",
|
||||
"sourceRoot": "src",
|
||||
"prefix": "app",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"outputPath": "dist/paperless-ui",
|
||||
"outputHashing": "none",
|
||||
"index": "src/index.html",
|
||||
"main": "src/main.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "tsconfig.app.json",
|
||||
"aot": true,
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/assets"
|
||||
],
|
||||
"styles": [
|
||||
"node_modules/bootstrap/dist/css/bootstrap.min.css",
|
||||
"src/styles.css"
|
||||
],
|
||||
"scripts": []
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.prod.ts"
|
||||
}
|
||||
],
|
||||
"optimization": true,
|
||||
"outputHashing": "none",
|
||||
"sourceMap": false,
|
||||
"extractCss": true,
|
||||
"namedChunks": false,
|
||||
"extractLicenses": true,
|
||||
"vendorChunk": false,
|
||||
"buildOptimizer": true,
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "2mb",
|
||||
"maximumError": "5mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "6kb",
|
||||
"maximumError": "10kb"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"builder": "@angular-devkit/build-angular:dev-server",
|
||||
"options": {
|
||||
"browserTarget": "paperless-ui:build"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"browserTarget": "paperless-ui:build:production"
|
||||
}
|
||||
}
|
||||
},
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"browserTarget": "paperless-ui:build"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "src/test.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "tsconfig.spec.json",
|
||||
"karmaConfig": "karma.conf.js",
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/assets"
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.css"
|
||||
],
|
||||
"scripts": []
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"tsconfig.app.json",
|
||||
"tsconfig.spec.json",
|
||||
"e2e/tsconfig.json"
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules/**"
|
||||
]
|
||||
}
|
||||
},
|
||||
"e2e": {
|
||||
"builder": "@angular-devkit/build-angular:protractor",
|
||||
"options": {
|
||||
"protractorConfig": "e2e/protractor.conf.js",
|
||||
"devServerTarget": "paperless-ui:serve"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"devServerTarget": "paperless-ui:serve:production"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}},
|
||||
"defaultProject": "paperless-ui"
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"version": 1,
|
||||
"newProjectRoot": "projects",
|
||||
"projects": {
|
||||
"paperless-ui": {
|
||||
"projectType": "application",
|
||||
"schematics": {
|
||||
"@schematics/angular:component": {
|
||||
"style": "scss"
|
||||
}
|
||||
},
|
||||
"root": "",
|
||||
"sourceRoot": "src",
|
||||
"prefix": "app",
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"outputPath": "dist/paperless-ui",
|
||||
"outputHashing": "none",
|
||||
"index": "src/index.html",
|
||||
"main": "src/main.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "tsconfig.app.json",
|
||||
"localize": true,
|
||||
"aot": true,
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/assets",
|
||||
"src/manifest.webmanifest", {
|
||||
"glob": "pdf.worker.min.js",
|
||||
"input": "node_modules/pdfjs-dist/build/",
|
||||
"output": "/assets/js/"
|
||||
}
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.scss"
|
||||
],
|
||||
"scripts": [],
|
||||
"allowedCommonJsDependencies": [
|
||||
"ng2-pdf-viewer"
|
||||
]
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.prod.ts"
|
||||
}
|
||||
],
|
||||
"outputPath": "../src/documents/static/frontend/",
|
||||
"optimization": true,
|
||||
"outputHashing": "none",
|
||||
"sourceMap": false,
|
||||
"extractCss": true,
|
||||
"namedChunks": false,
|
||||
"extractLicenses": true,
|
||||
"vendorChunk": false,
|
||||
"buildOptimizer": true,
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "2mb",
|
||||
"maximumError": "5mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "6kb",
|
||||
"maximumError": "10kb"
|
||||
}
|
||||
]
|
||||
},
|
||||
"en-US": {
|
||||
"localize": ["en-US"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"builder": "@angular-devkit/build-angular:dev-server",
|
||||
"options": {
|
||||
"browserTarget": "paperless-ui:build:en-US"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"browserTarget": "paperless-ui:build:production"
|
||||
}
|
||||
}
|
||||
},
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"browserTarget": "paperless-ui:build"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "src/test.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "tsconfig.spec.json",
|
||||
"karmaConfig": "karma.conf.js",
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/assets",
|
||||
"src/manifest.webmanifest"
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.scss"
|
||||
],
|
||||
"scripts": []
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"tsconfig.app.json",
|
||||
"tsconfig.spec.json",
|
||||
"e2e/tsconfig.json"
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules/**"
|
||||
]
|
||||
}
|
||||
},
|
||||
"e2e": {
|
||||
"builder": "@angular-devkit/build-angular:protractor",
|
||||
"options": {
|
||||
"protractorConfig": "e2e/protractor.conf.js",
|
||||
"devServerTarget": "paperless-ui:serve"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"devServerTarget": "paperless-ui:serve:production"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultProject": "paperless-ui"
|
||||
}
|
||||
|
2048
src-ui/messages.xlf
Normal file
90
src-ui/package-lock.json
generated
@@ -331,6 +331,12 @@
|
||||
"ms": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
|
||||
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
|
||||
"dev": true
|
||||
},
|
||||
"uuid": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz",
|
||||
@@ -2056,6 +2062,14 @@
|
||||
"tslib": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"@ng-select/ng-select": {
|
||||
"version": "5.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@ng-select/ng-select/-/ng-select-5.0.9.tgz",
|
||||
"integrity": "sha512-YZeSAiS8/Nx/eHZJPmOOYL8YmcvSq+dr1P8WIrsKmRA7mueorBpPc5xlUj+nLQbpLtsiQvdWDQspf/ykOvD/lA==",
|
||||
"requires": {
|
||||
"tslib": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"@ngtools/webpack": {
|
||||
"version": "10.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-10.2.0.tgz",
|
||||
@@ -2170,6 +2184,14 @@
|
||||
"pacote": "9.5.12",
|
||||
"semver": "7.3.2",
|
||||
"semver-intersect": "1.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
|
||||
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@types/glob": {
|
||||
@@ -2215,6 +2237,11 @@
|
||||
"integrity": "sha512-UV1/ZJMC+HcP902wWdpC43cAcGu0IQk/I5bXjP2aSuCjsk3cE74mDvFrLKga7oDC170ugOAYBwfT4DSQW3akDA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/pdfjs-dist": {
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/pdfjs-dist/-/pdfjs-dist-2.1.7.tgz",
|
||||
"integrity": "sha512-nQIwcPUhkAIyn7x9NS0lR/qxYfd5unRtfGkMjvpgF4Sh28IXftRymaNmFKTTdejDNY25NDGSIyjwj/BRwAPexg=="
|
||||
},
|
||||
"@types/q": {
|
||||
"version": "1.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz",
|
||||
@@ -3023,6 +3050,16 @@
|
||||
"integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==",
|
||||
"dev": true
|
||||
},
|
||||
"bindings": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
|
||||
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"file-uri-to-path": "1.0.0"
|
||||
}
|
||||
},
|
||||
"blob": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz",
|
||||
@@ -5508,6 +5545,18 @@
|
||||
"schema-utils": "^2.6.5"
|
||||
}
|
||||
},
|
||||
"file-saver": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz",
|
||||
"integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA=="
|
||||
},
|
||||
"file-uri-to-path": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
|
||||
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
@@ -8208,6 +8257,13 @@
|
||||
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
|
||||
"dev": true
|
||||
},
|
||||
"nan": {
|
||||
"version": "2.14.2",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz",
|
||||
"integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"nanomatch": {
|
||||
"version": "1.2.13",
|
||||
"resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
|
||||
@@ -8260,6 +8316,23 @@
|
||||
"moment": "2.18.1"
|
||||
}
|
||||
},
|
||||
"ng2-pdf-viewer": {
|
||||
"version": "6.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ng2-pdf-viewer/-/ng2-pdf-viewer-6.3.2.tgz",
|
||||
"integrity": "sha512-H2tBhDd+Lq6CUzK2g54HsCcZDR2wTn1sDjYqKY3yF0Ydasl2R5ppCKynZBU/zge4EKvmHglJI120FbQMpJKDYQ==",
|
||||
"requires": {
|
||||
"@types/pdfjs-dist": "^2.1.4",
|
||||
"pdfjs-dist": "^2.4.456",
|
||||
"tslib": "^1.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"tslib": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"ngx-cookie-service": {
|
||||
"version": "10.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ngx-cookie-service/-/ngx-cookie-service-10.1.1.tgz",
|
||||
@@ -9270,6 +9343,11 @@
|
||||
"sha.js": "^2.4.8"
|
||||
}
|
||||
},
|
||||
"pdfjs-dist": {
|
||||
"version": "2.5.207",
|
||||
"resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.5.207.tgz",
|
||||
"integrity": "sha512-xGDUhnCYPfHy+unMXCLCJtlpZaaZ17Ew3WIL0tnSgKFUZXHAPD49GO9xScyszSsQMoutNDgRb+rfBXIaX/lJbw=="
|
||||
},
|
||||
"performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
@@ -13228,7 +13306,11 @@
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
|
||||
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"bindings": "^1.5.0",
|
||||
"nan": "^2.12.1"
|
||||
}
|
||||
},
|
||||
"glob-parent": {
|
||||
"version": "3.1.0",
|
||||
@@ -13832,7 +13914,11 @@
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
|
||||
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"bindings": "^1.5.0",
|
||||
"nan": "^2.12.1"
|
||||
}
|
||||
},
|
||||
"glob-parent": {
|
||||
"version": "3.1.0",
|
||||
|
@@ -21,8 +21,11 @@
|
||||
"@angular/platform-browser-dynamic": "~10.1.5",
|
||||
"@angular/router": "~10.1.5",
|
||||
"@ng-bootstrap/ng-bootstrap": "^8.0.0",
|
||||
"@ng-select/ng-select": "^5.0.9",
|
||||
"bootstrap": "^4.5.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"ng-bootstrap": "^1.6.3",
|
||||
"ng2-pdf-viewer": "^6.3.2",
|
||||
"ngx-cookie-service": "^10.1.1",
|
||||
"ngx-file-drop": "^10.0.0",
|
||||
"ngx-infinite-scroll": "^9.1.0",
|
||||
|
@@ -1,14 +1,70 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { SettingsService, SETTINGS_KEYS } from './services/settings.service';
|
||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { ConsumerStatusService } from './services/consumer-status.service';
|
||||
import { ToastService } from './services/toast.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.css']
|
||||
styleUrls: ['./app.component.scss']
|
||||
})
|
||||
export class AppComponent {
|
||||
|
||||
constructor () {
|
||||
export class AppComponent implements OnInit, OnDestroy {
|
||||
|
||||
newDocumentSubscription: Subscription;
|
||||
successSubscription: Subscription;
|
||||
failedSubscription: Subscription;
|
||||
|
||||
constructor (private settings: SettingsService, private consumerStatusService: ConsumerStatusService, private toastService: ToastService, private router: Router) {
|
||||
let anyWindow = (window as any)
|
||||
anyWindow.pdfWorkerSrc = '/assets/js/pdf.worker.min.js';
|
||||
this.settings.updateDarkModeSettings()
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.consumerStatusService.disconnect()
|
||||
if (this.successSubscription) {
|
||||
this.successSubscription.unsubscribe()
|
||||
}
|
||||
if (this.failedSubscription) {
|
||||
this.failedSubscription.unsubscribe()
|
||||
}
|
||||
if (this.newDocumentSubscription) {
|
||||
this.newDocumentSubscription.unsubscribe()
|
||||
}
|
||||
}
|
||||
|
||||
private showNotification(key) {
|
||||
if (this.router.url == '/dashboard' && this.settings.get(SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_SUPPRESS_ON_DASHBOARD)) {
|
||||
return false
|
||||
}
|
||||
return this.settings.get(key)
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.consumerStatusService.connect()
|
||||
|
||||
|
||||
this.successSubscription = this.consumerStatusService.onDocumentConsumptionFinished().subscribe(status => {
|
||||
if (this.showNotification(SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_SUCCESS)) {
|
||||
this.toastService.show({title: $localize`Document added`, delay: 10000, content: $localize`Document ${status.filename} was added to paperless.`, actionName: $localize`Open document`, action: () => {
|
||||
this.router.navigate(['documents', status.documentId])
|
||||
}})
|
||||
}
|
||||
})
|
||||
|
||||
this.failedSubscription = this.consumerStatusService.onDocumentConsumptionFailed().subscribe(status => {
|
||||
if (this.showNotification(SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_FAILED)) {
|
||||
this.toastService.showError($localize`Could not add ${status.filename}\: ${status.message}`)
|
||||
}
|
||||
})
|
||||
|
||||
this.newDocumentSubscription = this.consumerStatusService.onDocumentDetected().subscribe(status => {
|
||||
if (this.showNotification(SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_NEW_DOCUMENT)) {
|
||||
this.toastService.show({title: $localize`New document detected`, delay: 5000, content: $localize`Document ${status.filename} is being processed by paperless.`})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -13,23 +13,26 @@ import { DocumentTypeListComponent } from './components/manage/document-type-lis
|
||||
import { LogsComponent } from './components/manage/logs/logs.component';
|
||||
import { SettingsComponent } from './components/manage/settings/settings.component';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { DatePipe } from '@angular/common';
|
||||
import { SafePipe } from './pipes/safe.pipe';
|
||||
import { DatePipe, registerLocaleData } from '@angular/common';
|
||||
import { NotFoundComponent } from './components/not-found/not-found.component';
|
||||
import { CorrespondentListComponent } from './components/manage/correspondent-list/correspondent-list.component';
|
||||
import { DeleteDialogComponent } from './components/common/delete-dialog/delete-dialog.component';
|
||||
import { ConfirmDialogComponent } from './components/common/confirm-dialog/confirm-dialog.component';
|
||||
import { CorrespondentEditDialogComponent } from './components/manage/correspondent-list/correspondent-edit-dialog/correspondent-edit-dialog.component';
|
||||
import { TagEditDialogComponent } from './components/manage/tag-list/tag-edit-dialog/tag-edit-dialog.component';
|
||||
import { DocumentTypeEditDialogComponent } from './components/manage/document-type-list/document-type-edit-dialog/document-type-edit-dialog.component';
|
||||
import { TagComponent } from './components/common/tag/tag.component';
|
||||
import { SearchComponent } from './components/search/search.component';
|
||||
import { ResultHightlightComponent } from './components/search/result-hightlight/result-hightlight.component';
|
||||
import { ResultHighlightComponent } from './components/search/result-highlight/result-highlight.component';
|
||||
import { PageHeaderComponent } from './components/common/page-header/page-header.component';
|
||||
import { AppFrameComponent } from './components/app-frame/app-frame.component';
|
||||
import { ToastsComponent } from './components/common/toasts/toasts.component';
|
||||
import { FilterEditorComponent } from './components/filter-editor/filter-editor.component';
|
||||
import { FilterEditorComponent } from './components/document-list/filter-editor/filter-editor.component';
|
||||
import { FilterableDropdownComponent } from './components/common/filterable-dropdown/filterable-dropdown.component';
|
||||
import { ToggleableDropdownButtonComponent } from './components/common/filterable-dropdown/toggleable-dropdown-button/toggleable-dropdown-button.component';
|
||||
import { DateDropdownComponent } from './components/common/date-dropdown/date-dropdown.component';
|
||||
import { DocumentCardLargeComponent } from './components/document-list/document-card-large/document-card-large.component';
|
||||
import { DocumentCardSmallComponent } from './components/document-list/document-card-small/document-card-small.component';
|
||||
import { BulkEditorComponent } from './components/document-list/bulk-editor/bulk-editor.component';
|
||||
import { NgxFileDropModule } from 'ngx-file-drop';
|
||||
import { TextComponent } from './components/common/input/text/text.component';
|
||||
import { SelectComponent } from './components/common/input/select/select.component';
|
||||
@@ -41,6 +44,32 @@ import { TagsComponent } from './components/common/input/tags/tags.component';
|
||||
import { SortableDirective } from './directives/sortable.directive';
|
||||
import { CookieService } from 'ngx-cookie-service';
|
||||
import { CsrfInterceptor } from './interceptors/csrf.interceptor';
|
||||
import { SavedViewWidgetComponent } from './components/dashboard/widgets/saved-view-widget/saved-view-widget.component';
|
||||
import { StatisticsWidgetComponent } from './components/dashboard/widgets/statistics-widget/statistics-widget.component';
|
||||
import { UploadFileWidgetComponent } from './components/dashboard/widgets/upload-file-widget/upload-file-widget.component';
|
||||
import { WidgetFrameComponent } from './components/dashboard/widgets/widget-frame/widget-frame.component';
|
||||
import { PdfViewerModule } from 'ng2-pdf-viewer';
|
||||
import { WelcomeWidgetComponent } from './components/dashboard/widgets/welcome-widget/welcome-widget.component';
|
||||
import { YesNoPipe } from './pipes/yes-no.pipe';
|
||||
import { FileSizePipe } from './pipes/file-size.pipe';
|
||||
import { FilterPipe } from './pipes/filter.pipe';
|
||||
import { DocumentTitlePipe } from './pipes/document-title.pipe';
|
||||
import { MetadataCollapseComponent } from './components/document-detail/metadata-collapse/metadata-collapse.component';
|
||||
import { SelectDialogComponent } from './components/common/select-dialog/select-dialog.component';
|
||||
import { NgSelectModule } from '@ng-select/ng-select';
|
||||
import { NumberComponent } from './components/common/input/number/number.component';
|
||||
import { SafePipe } from './pipes/safe.pipe';
|
||||
import { CustomDatePipe } from './pipes/custom-date.pipe';
|
||||
|
||||
import localeFr from '@angular/common/locales/fr';
|
||||
import localeNl from '@angular/common/locales/nl';
|
||||
import localeDe from '@angular/common/locales/de';
|
||||
import localeEnGb from '@angular/common/locales/en-GB';
|
||||
|
||||
registerLocaleData(localeFr)
|
||||
registerLocaleData(localeNl)
|
||||
registerLocaleData(localeDe)
|
||||
registerLocaleData(localeEnGb)
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@@ -53,28 +82,45 @@ import { CsrfInterceptor } from './interceptors/csrf.interceptor';
|
||||
DocumentTypeListComponent,
|
||||
LogsComponent,
|
||||
SettingsComponent,
|
||||
SafePipe,
|
||||
NotFoundComponent,
|
||||
CorrespondentEditDialogComponent,
|
||||
DeleteDialogComponent,
|
||||
ConfirmDialogComponent,
|
||||
TagEditDialogComponent,
|
||||
DocumentTypeEditDialogComponent,
|
||||
TagComponent,
|
||||
SearchComponent,
|
||||
ResultHightlightComponent,
|
||||
ResultHighlightComponent,
|
||||
PageHeaderComponent,
|
||||
AppFrameComponent,
|
||||
ToastsComponent,
|
||||
FilterEditorComponent,
|
||||
FilterableDropdownComponent,
|
||||
ToggleableDropdownButtonComponent,
|
||||
DateDropdownComponent,
|
||||
DocumentCardLargeComponent,
|
||||
DocumentCardSmallComponent,
|
||||
BulkEditorComponent,
|
||||
TextComponent,
|
||||
SelectComponent,
|
||||
CheckComponent,
|
||||
SaveViewConfigDialogComponent,
|
||||
DateTimeComponent,
|
||||
TagsComponent,
|
||||
SortableDirective
|
||||
SortableDirective,
|
||||
SavedViewWidgetComponent,
|
||||
StatisticsWidgetComponent,
|
||||
UploadFileWidgetComponent,
|
||||
WidgetFrameComponent,
|
||||
WelcomeWidgetComponent,
|
||||
YesNoPipe,
|
||||
FileSizePipe,
|
||||
FilterPipe,
|
||||
DocumentTitlePipe,
|
||||
MetadataCollapseComponent,
|
||||
SelectDialogComponent,
|
||||
NumberComponent,
|
||||
SafePipe,
|
||||
CustomDatePipe
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
@@ -84,7 +130,9 @@ import { CsrfInterceptor } from './interceptors/csrf.interceptor';
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
NgxFileDropModule,
|
||||
InfiniteScrollModule
|
||||
InfiniteScrollModule,
|
||||
PdfViewerModule,
|
||||
NgSelectModule
|
||||
],
|
||||
providers: [
|
||||
DatePipe,
|
||||
@@ -92,7 +140,9 @@ import { CsrfInterceptor } from './interceptors/csrf.interceptor';
|
||||
provide: HTTP_INTERCEPTORS,
|
||||
useClass: CsrfInterceptor,
|
||||
multi: true
|
||||
}
|
||||
},
|
||||
FilterPipe,
|
||||
DocumentTitlePipe
|
||||
],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
|
@@ -1,84 +0,0 @@
|
||||
|
||||
/*
|
||||
* Sidebar
|
||||
*/
|
||||
|
||||
.sidebar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 100; /* Behind the navbar */
|
||||
padding: 48px 0 0; /* Height of navbar */
|
||||
box-shadow: inset -1px 0 0 rgba(0, 0, 0, .1);
|
||||
}
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
.sidebar {
|
||||
top: 5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-sticky {
|
||||
position: relative;
|
||||
top: 0;
|
||||
height: calc(100vh - 48px);
|
||||
padding-top: .5rem;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
|
||||
}
|
||||
|
||||
@supports ((position: -webkit-sticky) or (position: sticky)) {
|
||||
.sidebar-sticky {
|
||||
position: -webkit-sticky;
|
||||
position: sticky;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar .nav-link {
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.sidebar .nav-link .sidebaricon {
|
||||
margin-right: 4px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.sidebar .nav-link.active {
|
||||
color: #007bff;
|
||||
}
|
||||
|
||||
.sidebar .nav-link:hover .sidebaricon,
|
||||
.sidebar .nav-link.active .sidebaricon {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.sidebar-heading {
|
||||
font-size: .75rem;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Navbar
|
||||
*/
|
||||
|
||||
.navbar-brand {
|
||||
padding-top: .75rem;
|
||||
padding-bottom: .75rem;
|
||||
font-size: 1rem;
|
||||
background-color: rgba(0, 0, 0, .25);
|
||||
box-shadow: inset -1px 0 0 rgba(0, 0, 0, .25);
|
||||
}
|
||||
|
||||
.navbar .navbar-toggler {
|
||||
top: .25rem;
|
||||
right: 1rem;
|
||||
}
|
||||
|
||||
.navbar .form-control {
|
||||
padding: .75rem 1rem;
|
||||
border-width: 0;
|
||||
border-radius: 0;
|
||||
}
|