diff --git a/Pipfile b/Pipfile index bf8736557..95727aeeb 100644 --- a/Pipfile +++ b/Pipfile @@ -35,3 +35,4 @@ pytest-xdist = "*" [dev-packages] ipython = "*" +sphinx = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 1bc991c5f..09cfb8639 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "928fbb4c8952128aef7a2ed2707ce510d31d49df96cfc5f08959698edff6e67f" + "sha256": "70653513e6c80b7e07f8e7fbff7592f2d22749dc5b1d723a04f921242bc9a78f" }, "pipfile-spec": 6, "requires": {}, @@ -16,24 +16,32 @@ "default": { "apipkg": { "hashes": [ - "sha256:2e38399dbe842891fe85392601aab8f40a8f4cc5a9053c326de35a1cc0297ac6", - "sha256:65d2aa68b28e7d31233bb2ba8eb31cda40e4671f8ac2d6b241e358c9652a74b9" + "sha256:37228cda29411948b422fae072f57e31d3396d2ee1c9783775980ee9c9990af6", + "sha256:58587dd4dc3daefad0487f6d9ae32b4542b185e1c36db6993290e7c41ca2b47c" ], - "version": "==1.4" + "markers": "python_version != '3.0.*' and python_version >= '2.7' and python_version != '3.2.*' and python_version != '3.1.*' and python_version != '3.3.*'", + "version": "==1.5" + }, + "atomicwrites": { + "hashes": [ + "sha256:240831ea22da9ab882b551b31d4225591e5e447a68c5e188db5b89ca1d487585", + "sha256:a24da68318b08ac9c9c45029f4a10371ab5b20e4226738e150e6e7c571630ae6" + ], + "version": "==1.1.5" }, "attrs": { "hashes": [ - "sha256:1c7960ccfd6a005cd9f7ba884e6316b5e430a3f1a6c37c5f87d8b43f83b54ec9", - "sha256:a17a9573a6f475c99b551c0e0a812707ddda1ec9653bed04c13841404ed6f450" + "sha256:4b90b09eeeb9b88c35bc642cbac057e45a5fd85367b985bd2809c62b7b939265", + "sha256:e0d0eb91441a3b53dab4d9b743eafc1ac44476296a2053b6ca3af0b139faf87b" ], - "version": "==17.4.0" + "version": "==18.1.0" }, "certifi": { "hashes": [ - "sha256:14131608ad2fd56836d33a71ee60fa1c82bc9d2c8d98b7bdbc631fe1b3cd1296", - "sha256:edbc3f203427eef571f79a7692bb160a2b0f7ccaa31953e99bd17e307cf63f7d" + "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7", + "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0" ], - "version": "==2018.1.18" + "version": "==2018.4.16" }, "chardet": { "hashes": [ @@ -46,10 +54,7 @@ "hashes": [ "sha256:03481e81d558d30d230bc12999e3edffe392d244349a90f4ef9b88425fac74ba", "sha256:0b136648de27201056c1869a6c0d4e23f464750fd9a9ba9750b8336a244429ed", - "sha256:104ab3934abaf5be871a583541e8829d6c19ce7bde2923b2751e0d3ca44db60a", - "sha256:15b111b6a0f46ee1a485414a52a7ad1d703bdf984e9ed3c288a4414d3871dcbd", "sha256:198626739a79b09fa0a2f06e083ffd12eb55449b5f8bfdbeed1df4910b2ca640", - "sha256:1c383d2ef13ade2acc636556fd544dba6e14fa30755f26812f54300e401f98f2", "sha256:28b2191e7283f4f3568962e373b47ef7f0392993bb6660d079c62bd50fe9d162", "sha256:2eb564bbf7816a9d68dd3369a510be3327f1c618d2357fa6b1216994c2e3d508", "sha256:337ded681dd2ef9ca04ef5d93cfc87e52e09db2594c296b4a0a3662cb1b41249", @@ -70,16 +75,11 @@ "sha256:7e1fe19bd6dce69d9fd159d8e4a80a8f52101380d5d3a4d374b6d3eae0e5de9c", "sha256:8c3cb8c35ec4d9506979b4cf90ee9918bc2e49f84189d9bf5c36c0c1119c6558", "sha256:9d6dd10d49e01571bf6e147d3b505141ffc093a06756c60b053a859cb2128b1f", - "sha256:9e112fcbe0148a6fa4f0a02e8d58e94470fc6cb82a5481618fea901699bf34c4", - "sha256:ac4fef68da01116a5c117eba4dd46f2e06847a497de5ed1d64bb99a5fda1ef91", - "sha256:b8815995e050764c8610dbc82641807d196927c3dbed207f0a079833ffcf588d", "sha256:be6cfcd8053d13f5f5eeb284aa8a814220c3da1b0078fa859011c7fffd86dab9", "sha256:c1bb572fab8208c400adaf06a8133ac0712179a334c09224fb11393e920abcdd", "sha256:de4418dadaa1c01d497e539210cb6baa015965526ff5afc078c57ca69160108d", "sha256:e05cb4d9aad6233d67e0541caa7e511fa4047ed7750ec2510d466e806e0255d6", - "sha256:e4d96c07229f58cb686120f168276e434660e4358cc9cf3b0464210b04913e77", - "sha256:f3f501f345f24383c0000395b26b726e46758b71393267aeae0bd36f8b3ade80", - "sha256:f8a923a85cb099422ad5a2e345fe877bbc89a8a8b23235824a93488150e45f6e" + "sha256:f3f501f345f24383c0000395b26b726e46758b71393267aeae0bd36f8b3ade80" ], "version": "==4.5.1" }, @@ -101,11 +101,11 @@ }, "django": { "hashes": [ - "sha256:056fe5b9e1f8f7fed9bb392919d64f6b33b3a71cfb0f170a90ee277a6ed32bc2", - "sha256:4d398c7b02761e234bbde490aea13ea94cb539ceeb72805b72303f348682f2eb" + "sha256:b7f77c0d168de4c4ad30a02ae31b9dca04fb3c10472f04918d5c02b4117bba68", + "sha256:eb9271f0874f53106a2719c0c35ce67631f6cc27cf81a60c6f8c9817b35a3f6e" ], "index": "pypi", - "version": "==1.11.12" + "version": "==1.11.14" }, "django-crispy-forms": { "hashes": [ @@ -117,11 +117,11 @@ }, "django-extensions": { "hashes": [ - "sha256:37a543af370ee3b0721ff50442d33c357dd083e6ea06c5b94a199283b6f9e361", - "sha256:bc9f2946c117bb2f49e5e0633eba783787790ae810ea112fe7fd82fa64de2ff1" + "sha256:3be3debf53c77ca795bdf713726c923aa3c3f895e1a42e2e31a68c1a562346a4", + "sha256:94bfac99eb262c5ac27e53eda96925e2e53fe0b331af7dde37012d07639a649c" ], "index": "pypi", - "version": "==2.0.6" + "version": "==2.0.7" }, "django-filter": { "hashes": [ @@ -161,18 +161,18 @@ }, "factory-boy": { "hashes": [ - "sha256:bd5a096d0f102d79b6c78cef1c8c0b650f2e1a3ecba351c735c6d2df8dabd29c", - "sha256:be2abc8092294e4097935a29b4e37f5b9ed3e4205e2e32df215c0315b625995e" + "sha256:6f25cc4761ac109efd503f096e2ad99421b1159f01a29dbb917359dcd68e08ca", + "sha256:d552cb872b310ae78bd7429bf318e42e1e903b1a109e899a523293dfa762ea4f" ], "index": "pypi", - "version": "==2.10.0" + "version": "==2.11.1" }, "faker": { "hashes": [ - "sha256:226d8fa67a8cf8b4007aab721f67639f130e9cfdc53a7095a2290ebb07a65c71", - "sha256:48fed4b4a191e2b42ad20c14115f1c6d36d338b80192075d7573f0f42d7fb321" + "sha256:04645d946256b835c675c1cef7c03817a164b0c4e452018fd50b212ddff08c22", + "sha256:fe48f35aa3443bc5655b0782d3a2f594bf4882d0e2a947b80207a60494d32907" ], - "version": "==0.8.13" + "version": "==0.8.16" }, "filemagic": { "hashes": [ @@ -195,22 +195,23 @@ "sha256:5b36957ccf836e700f4468324fa80ba208990385392e217be077d5cd738ae602" ], "index": "pypi", + "markers": null, "version": "==0.15.0" }, "gunicorn": { "hashes": [ - "sha256:75af03c99389535f218cc596c7de74df4763803f7b63eb09d77e92b3956b36c6", - "sha256:eee1169f0ca667be05db3351a0960765620dad53f53434262ff8901b68a1b622" + "sha256:aa8e0b40b4157b36a5df5e599f45c9c76d6af43845ba3b3b0efe2c70473c2471", + "sha256:fa2662097c66f920f53f70621c6c58ca4a3c4d3434205e608e121b5b3b71f4f3" ], "index": "pypi", - "version": "==19.7.1" + "version": "==19.9.0" }, "idna": { "hashes": [ - "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f", - "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4" + "sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e", + "sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16" ], - "version": "==2.6" + "version": "==2.7" }, "langdetect": { "hashes": [ @@ -228,71 +229,57 @@ }, "more-itertools": { "hashes": [ - "sha256:0dd8f72eeab0d2c3bd489025bb2f6a1b8342f9b198f6fc37b52d15cfa4531fea", - "sha256:11a625025954c20145b37ff6309cd54e39ca94f72f6bb9576d1195db6fa2442e", - "sha256:c9ce7eccdcb901a2c75d326ea134e0886abfbea5f93e91cc95de9507c0816c44" + "sha256:2b6b9893337bfd9166bee6a62c2b0c9fe7735dcf85948b387ec8cba30e85d8e8", + "sha256:6703844a52d3588f951883005efcf555e49566a48afd4db4e965d69b883980d3", + "sha256:a18d870ef2ffca2b8463c0070ad17b5978056f403fb64e3f15fe62a52db21cc0" ], - "version": "==4.1.0" + "version": "==4.2.0" }, "pdftotext": { "hashes": [ - "sha256:0b82a9fd255a3f2bf5c861cf9e3174d3c4223e1e441bb060c611dcb4e65c6cb8" + "sha256:b7312302007e19fc784263a321b41682f01a582af84e14200cef53b3f4e69a50" ], "index": "pypi", - "version": "==2.0.2" + "version": "==2.1.0" }, "pillow": { "hashes": [ - "sha256:00633bc2ec40313f4daf351855e506d296ec3c553f21b66720d0f1225ca84c6f", - "sha256:03514478db61b034fc5d38b9bf060f994e5916776e93f02e59732a8270069c61", - "sha256:040144ba422216aecf7577484865ade90e1a475f867301c48bf9fbd7579efd76", - "sha256:16246261ff22368e5e32ad74d5ef40403ab6895171a7fc6d34f6c17cfc0f1943", - "sha256:1cb38df69362af35c14d4a50123b63c7ff18ec9a6d4d5da629a6f19d05e16ba8", - "sha256:2400e122f7b21d9801798207e424cbe1f716cee7314cd0c8963fdb6fc564b5fb", - "sha256:2ee6364b270b56a49e8b8a51488e847ab130adc1220c171bed6818c0d4742455", - "sha256:3b4560c3891b05022c464b09121bd507c477505a4e19d703e1027a3a7c68d896", - "sha256:41374a6afb3f44794410dab54a0d7175e6209a5a02d407119c81083f1a4c1841", - "sha256:438a3faf5f702c8d0f80b9f9f9b8382cfa048ca6a0d64ef71b86b563b0ee0359", - "sha256:472a124c640bde4d5468f6991c9fa7e30b723d84ac4195a77c6ab6aea30f2b9c", - "sha256:4d32c8e3623a61d6e29ccd024066cd1ba556555abfb4cd714155020e00107e3f", - "sha256:4d8077fd649ac40a5c4165f2c22fa2a4ad18c668e271ecb2f9d849d1017a9313", - "sha256:62ec7ae98357fcd46002c110bb7cad15fce532776f0cbe7ca1d44c49b837d49d", - "sha256:6c7cab6a05351cf61e469937c49dbf3cdf5ffb3eeac71f8d22dc9be3507598d8", - "sha256:6eca36905444c4b91fe61f1b9933a47a30480738a1dd26501ff67d94fc2bc112", - "sha256:74e2ebfd19c16c28ad43b8a28ff73b904ed382ea4875188838541751986e8c9a", - "sha256:7673e7473a13107059377c96c563aa36f73184c29d2926882e0a0210b779a1e7", - "sha256:81762cf5fca9a82b53b7b2d0e6b420e0f3b06167b97678c81d00470daa622d58", - "sha256:8554bbeb4218d9cfb1917c69e6f2d2ad0be9b18a775d2162547edf992e1f5f1f", - "sha256:9b66e968da9c4393f5795285528bc862c7b97b91251f31a08004a3c626d18114", - "sha256:a00edb2dec0035e98ac3ec768086f0b06dfabb4ad308592ede364ef573692f55", - "sha256:b48401752496757e95304a46213c3155bc911ac884bed2e9b275ce1c1df3e293", - "sha256:b6cf18f9e653a8077522bb3aa753a776b117e3e0cc872c25811cfdf1459491c2", - "sha256:bb8adab1877e9213385cbb1adc297ed8337e01872c42a30cfaa66ff8c422779c", - "sha256:c8a4b39ba380b57a31a4b5449a9d257b1302d8bc4799767e645dcee25725efe1", - "sha256:cee9bc75bff455d317b6947081df0824a8f118de2786dc3d74a3503fd631f4ef", - "sha256:d0dc1313dff48af64517cbbd85e046d6b477fbe5e9d69712801f024dcb08c62b", - "sha256:d5bf527ed83617edd1855a5c923eeeaf68bcb9ac0ceb28e3f19b575b3a424984", - "sha256:df5863a21f91de5ecdf7d32a32f406dd9867ebb35d41033b8bd9607a21887599", - "sha256:e39142332541ed2884c257495504858b22c078a5d781059b07aba4c3a80d7551", - "sha256:e52e8f675ba0b2b417fa98579e7286a41a8e23871f17f4793772f5aa884fea79", - "sha256:e6dd55d5d94b9e36929325dd0c9ab85bfde84a5fc35947c334c32af1af668944", - "sha256:e87cc1acbebf263f308a8494272c2d42016aa33c32bf14d209c81e1f65e11868", - "sha256:ea0091cd4100519cedfeea2c659f52291f535ac6725e2368bcf59e874f270efa", - "sha256:eeb247f4f4d962942b3b555530b0c63b77473c7bfe475e51c6b75b7344b49ce3", - "sha256:f0d4433adce6075efd24fc0285135248b0b50f5a58129c7e552030e04fe45c7f", - "sha256:f1f3bd92f8e12dc22884935a73c9f94c4d9bd0d34410c456540713d6b7832b8c", - "sha256:f42a87cbf50e905f49f053c0b1fb86c911c730624022bf44c8857244fc4cdaca", - "sha256:f5f302db65e2e0ae96e26670818157640d3ca83a3054c290eff3631598dcf819", - "sha256:f7634d534662bbb08976db801ba27a112aee23e597eeaf09267b4575341e45bf", - "sha256:fdd374c02e8bb2d6468a85be50ea66e1c4ef9e809974c30d8576728473a6ed03", - "sha256:fe6931db24716a0845bd8c8915bd096b77c2a7043e6fc59ae9ca364fe816f08b" + "sha256:00def5b638994f888d1058e4d17c86dec8e1113c3741a0a8a659039aec59a83a", + "sha256:026449b64e559226cdb8e6d8c931b5965d8fc90ec18ebbb0baa04c5b36503c72", + "sha256:03dbb224ee196ef30ed2156d41b579143e1efeb422974719a5392fc035e4f574", + "sha256:03eb0e04f929c102ae24bc436bf1c0c60a4e63b07ebd388e84d8b219df3e6acd", + "sha256:1be66b9a89e367e7d20d6cae419794997921fe105090fafd86ef39e20a3baab2", + "sha256:1e977a3ed998a599bda5021fb2c2889060617627d3ae228297a529a082a3cd5c", + "sha256:22cf3406d135cfcc13ec6228ade774c8461e125c940e80455f500638429be273", + "sha256:24adccf1e834f82718c7fc8e3ec1093738da95144b8b1e44c99d5fc7d3e9c554", + "sha256:2a3e362c97a5e6a259ee9cd66553292a1f8928a5bdfa3622fdb1501570834612", + "sha256:3832e26ecbc9d8a500821e3a1d3765bda99d04ae29ffbb2efba49f5f788dc934", + "sha256:4fd1f0c2dc02aaec729d91c92cd85a2df0289d88e9f68d1e8faba750bb9c4786", + "sha256:4fda62030f2c515b6e2e673c57caa55cb04026a81968f3128aae10fc28e5cc27", + "sha256:5044d75a68b49ce36a813c82d8201384207112d5d81643937fc758c05302f05b", + "sha256:522184556921512ec484cb93bd84e0bab915d0ac5a372d49571c241a7f73db62", + "sha256:5914cff11f3e920626da48e564be6818831713a3087586302444b9c70e8552d9", + "sha256:6661a7908d68c4a133e03dac8178287aa20a99f841ea90beeb98a233ae3fd710", + "sha256:79258a8df3e309a54c7ef2ef4a59bb8e28f7e4a8992a3ad17c24b1889ced44f3", + "sha256:7d74c20b8f1c3e99d3f781d3b8ff5abfefdd7363d61e23bdeba9992ff32cc4b4", + "sha256:81918afeafc16ba5d9d0d4e9445905f21aac969a4ebb6f2bff4b9886da100f4b", + "sha256:8194d913ca1f459377c8a4ed8f9b7ad750068b8e0e3f3f9c6963fcc87a84515f", + "sha256:84d5d31200b11b3c76fab853b89ac898bf2d05c8b3da07c1fcc23feb06359d6e", + "sha256:989981db57abffb52026b114c9a1f114c7142860a6d30a352d28f8cbf186500b", + "sha256:a3d7511d3fad1618a82299aab71a5fceee5c015653a77ffea75ced9ef917e71a", + "sha256:b3ef168d4d6fd4fa6685aef7c91400f59f7ab1c0da734541f7031699741fb23f", + "sha256:c1c5792b6e74bbf2af0f8e892272c2a6c48efa895903211f11b8342e03129fea", + "sha256:c5dcb5a56aebb8a8f2585042b2f5c496d7624f0bcfe248f0cc33ceb2fd8d39e7", + "sha256:e2bed4a04e2ca1050bb5f00865cf2f83c0b92fd62454d9244f690fcd842e27a4", + "sha256:e87a527c06319428007e8c30511e1f0ce035cb7f14bb4793b003ed532c3b9333", + "sha256:f63e420180cbe22ff6e32558b612e75f50616fc111c5e095a4631946c782e109", + "sha256:f8b3d413c5a8f84b12cd4c5df1d8e211777c9852c6be3ee9c094b626644d3eab" ], "index": "pypi", - "version": "==5.1.0" + "version": "==5.2.0" }, "pluggy": { "hashes": [ - "sha256:714306e9b9a7b24ee4c1e3ff6463d7f652cdd30f4693121b31572e2fe1fdaea3", "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff", "sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c", "sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5" @@ -301,15 +288,14 @@ }, "py": { "hashes": [ - "sha256:29c9fab495d7528e80ba1e343b958684f4ace687327e6f789a94bf3d1915f881", - "sha256:983f77f3331356039fdd792e9220b7b8ee1aa6bd2b25f567a963ff1de5a64f6a" + "sha256:3fd59af7435864e1a243790d322d763925431213b6b8529c6ca71081ace3bbf7", + "sha256:e31fb2767eb657cbde86c454f02e99cb846d3cd9d61b318525140214fdc0e98e" ], - "version": "==1.5.3" + "markers": "python_version != '3.0.*' and python_version != '3.3.*' and python_version != '3.1.*' and python_version != '3.2.*' and python_version >= '2.7'", + "version": "==1.5.4" }, "pycodestyle": { "hashes": [ - "sha256:1ec08a51c901dfe44921576ed6e4c1f5b7ecbad403f871397feedb5eb8e4fa14", - "sha256:5ff2fbcbab997895ba9ead77e1b38b3ebc2e5c3b8a6194ef918666e4c790a00e", "sha256:682256a5b318149ca0d2a9185d365d8864a768a28db66a84a2ea946bcc426766", "sha256:6c4245ade1edfad79c3446fadfc96b0de2759662dc29d07d80a6f27ad1ca6ba9" ], @@ -332,11 +318,11 @@ }, "pytest": { "hashes": [ - "sha256:6266f87ab64692112e5477eba395cfedda53b1933ccd29478e671e73b420c19c", - "sha256:fae491d1874f199537fd5872b5e1f0e74a009b979df9d53d1553fd03da1703e1" + "sha256:0453c8676c2bee6feb0434748b068d5510273a916295fd61d306c4f22fbfd752", + "sha256:4b208614ae6d98195430ad6bde03641c78553acee7c83cec2e85d613c0cd383d" ], "index": "pypi", - "version": "==3.5.0" + "version": "==3.6.3" }, "pytest-cov": { "hashes": [ @@ -348,11 +334,11 @@ }, "pytest-django": { "hashes": [ - "sha256:534505e0261cc566279032d9d887f844235342806fd63a6925689670fa1b29d7", - "sha256:7501942093db2250a32a4e36826edfc542347bb9b26c78ed0649cdcfd49e5789" + "sha256:088b66211c57972e7bd072ba73ccec1c3b6f6185f894b3b8eb966d2f3b7d46cb", + "sha256:3fea4d0a84bf3af1f1e82448b9a91b3ddb22b659d802e026ae843040da0c3220" ], "index": "pypi", - "version": "==3.2.1" + "version": "==3.3.2" }, "pytest-env": { "hashes": [ @@ -385,11 +371,11 @@ }, "python-dateutil": { "hashes": [ - "sha256:3220490fb9741e2342e1cf29a503394fdac874bc39568288717ee67047ff29df", - "sha256:9d8074be4c993fbe4947878ce593052f71dac82932a677d49194d8ce9778002e" + "sha256:1adb80e7a782c12e52ef9a8182bebeb73f1d7e24e374397af06fb4956c8dc5c0", + "sha256:e27001de32f627c22380a688bcc43ce83504a7bc5da472209b4c70f02829f0b8" ], "index": "pypi", - "version": "==2.7.2" + "version": "==2.7.3" }, "python-dotenv": { "hashes": [ @@ -401,11 +387,11 @@ }, "python-gnupg": { "hashes": [ - "sha256:38f18712b7cfdd0d769bc88a21e90138154b9be2cbffb1e7d28bc37ee73a1c47", - "sha256:5a54a6dd25bf78d3758dd7a1864f4efd122f9ca9402101d90e3ec4483ceafb73" + "sha256:2d158dfc6b54927752b945ebe57e6a0c45da27747fa3b9ae66eccc0d2147ac0d", + "sha256:faa69bab58ed0936f0ccf96c99b92369b7a1819305d37dfe5c927d21a437a09d" ], "index": "pypi", - "version": "==0.4.2" + "version": "==0.4.3" }, "python-levenshtein": { "hashes": [ @@ -415,38 +401,38 @@ }, "pytz": { "hashes": [ - "sha256:65ae0c8101309c45772196b21b74c46b2e5d11b6275c45d251b150d5da334555", - "sha256:c06425302f2cf668f1bba7a0a03f3c1d34d4ebeef2c72003da308b3947c7f749" + "sha256:a061aa0a9e06881eb8b3b2b43f05b9439d6583c206d0a6c340ff72a7b6669053", + "sha256:ffb9ef1de172603304d9d2819af6f5ece76f2e85ec10692a524dd876e72bf277" ], "index": "pypi", - "version": "==2018.4" + "version": "==2018.5" }, "regex": { "hashes": [ - "sha256:1b428a296531ea1642a7da48562746309c5c06471a97bd0c02dd6a82e9cecee8", - "sha256:27d72bb42dffb32516c28d218bb054ce128afd3e18464f30837166346758af67", - "sha256:32cf4743debee9ea12d3626ee21eae83052763740e04086304e7a74778bf58c9", - "sha256:32f6408dbca35040bc65f9f4ae1444d5546411fde989cb71443a182dd643305e", - "sha256:333687d9a44738c486735955993f83bd22061a416c48f5a5f9e765e90cf1b0c9", - "sha256:35eeccf17af3b017a54d754e160af597036435c58eceae60f1dd1364ae1250c7", - "sha256:361a1fd703a35580a4714ec28d85e29780081a4c399a99bbfb2aee695d72aedb", - "sha256:494bed6396a20d3aa6376bdf2d3fbb1005b8f4339558d8ac7b53256755f80303", - "sha256:5b9c0ddd5b4afa08c9074170a2ea9b34ea296e32aeea522faaaaeeeb2fe0af2e", - "sha256:a50532f61b23d4ab9d216a6214f359dd05c911c1a1ad20986b6738a782926c1a", - "sha256:a9243d7b359b72c681a2c32eaa7ace8d346b7e8ce09d172a683acf6853161d9c", - "sha256:b44624a38d07d3c954c84ad302c29f7930f4bf01443beef5589e9157b14e2a29", - "sha256:be42a601aaaeb7a317f818490a39d153952a97c40c6e9beeb2a1103616405348", - "sha256:eee4d94b1a626490fc8170ffd788883f8c641b576e11ba9b4a29c9f6623371e0", - "sha256:f69d1201a4750f763971ea8364ed95ee888fc128968b39d38883a72a4d005895" + "sha256:0f935c4b04b60bf3904bcaa11dec702a49de61caff3b09793521759f61bd7585", + "sha256:22a561fce0691e2819f8b4957b0a6a1829ec1df503e93569a015a01c173b401c", + "sha256:2fc09d427dfc7f53ed1261caf357b25932409fd1be4dae3f3bc70e353a7120bb", + "sha256:309f05c0a93a1410d1250f4170257d3f4092a7a4460e46ef47925db7c930b9c6", + "sha256:3e985c6980badbf97497945cd922561639e12e7f4174f735979136c0d81cc1b4", + "sha256:5cdfe2f16d674e2e7b341c0cd0b12cc4644d2adf248ff860c0dc74494397f001", + "sha256:717ed720c872a0c4458d8de81660e1e1e5c9a3f4277b782e01d5df934e50a820", + "sha256:81709bdab6fb5db389a3123f28f7198921372144fbda03b8ab8162ef9688b61c", + "sha256:97d286c501c2007e43003b53a997102d5ca781fd3d9228427f942779ac43b107", + "sha256:a35138a333069cf1d19ec39e1b1aaa868a474cf215303af2bb5d08b747796d9a", + "sha256:b172583f0c5f104e059a30dd6a1f9d20693031b156558590a745d6cc3192e283", + "sha256:b5a739fff4f0bfeba6d889820a14b359f50bcc3466afe00ce616fd5cb9093e25", + "sha256:b65b3a347a33fec024133cd21f926f6bff1fae387ff2f380b8751a8b26a6b92c", + "sha256:c42af0a812c272339ac9602bf10e5d1e022e518e5936c303624b5c11803805e3", + "sha256:d421ee4a55922f2ff2561cae543458f5bff089b5a94c7dfcf60b6bef5721cd0f" ], - "version": "==2018.2.21" + "version": "==2018.6.21" }, "requests": { "hashes": [ - "sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b", - "sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e" + "sha256:63b52e3c866428a224f97cab011de738c36aec0185aa91cfacd418b5d58911d1", + "sha256:ec22d826a36ed72a7358ff3fe56cbd4ba69dd7a6718ffd450ff0e9df7a47ce6a" ], - "version": "==2.18.4" + "version": "==2.19.1" }, "six": { "hashes": [ @@ -476,13 +462,27 @@ }, "urllib3": { "hashes": [ - "sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b", - "sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f" + "sha256:a68ac5e15e76e7e5dd2b8f94007233e01effe3e50e8daddf69acfd81cb686baf", + "sha256:b5725a0bd4ba422ab0e66e89e030c806576753ea3ee08554382c14e685d117b5" ], - "version": "==1.22" + "version": "==1.23" } }, "develop": { + "alabaster": { + "hashes": [ + "sha256:674bb3bab080f598371f4443c5008cbfeb1a5e622dd312395d2d82af2c54c456", + "sha256:b63b1f4dc77c074d386752ec4a8a7517600f6c0db8cd42980cae17ab7b3275d7" + ], + "version": "==0.7.11" + }, + "babel": { + "hashes": [ + "sha256:6778d85147d5d85345c14a26aada5e478ab04e39b078b0745ee6870c2b5cf669", + "sha256:8cba50f48c529ca3fa18cf81fa9403be176d374ac4d60738b839122dfaaa3d23" + ], + "version": "==2.6.0" + }, "backcall": { "hashes": [ "sha256:38ecd85be2c1e78f77fd91700c76e14667dc21e2713b63876c0eb901196e01e4", @@ -490,6 +490,20 @@ ], "version": "==0.1.0" }, + "certifi": { + "hashes": [ + "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7", + "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0" + ], + "version": "==2018.4.16" + }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + ], + "version": "==3.0.4" + }, "decorator": { "hashes": [ "sha256:2c51dff8ef3c447388fe5e4453d24a2bf128d3a4c32af3fabef1f01c6851ab82", @@ -497,13 +511,35 @@ ], "version": "==4.3.0" }, + "docutils": { + "hashes": [ + "sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6", + "sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274", + "sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6" + ], + "version": "==0.14" + }, + "idna": { + "hashes": [ + "sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e", + "sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16" + ], + "version": "==2.7" + }, + "imagesize": { + "hashes": [ + "sha256:3620cc0cadba3f7475f9940d22431fc4d407269f1be59ec9b8edcca26440cf18", + "sha256:5b326e4678b6925158ccc66a9fa3122b6106d7c876ee32d7de6ce59385b96315" + ], + "version": "==1.0.0" + }, "ipython": { "hashes": [ - "sha256:85882f97d75122ff8cdfe129215a408085a26039527110c8d4a2b8a5e45b7639", - "sha256:a6ac981381b3f5f604b37a293369963485200e3639fb0404fa76092383c10c41" + "sha256:a0c96853549b246991046f32d19db7140f5b1a644cc31f0dc1edc86713b7676f", + "sha256:eca537aa61592aca2fef4adea12af8e42f5c335004dfa80c78caf80e8b525e5c" ], "index": "pypi", - "version": "==6.3.1" + "version": "==6.4.0" }, "ipython-genutils": { "hashes": [ @@ -514,25 +550,45 @@ }, "jedi": { "hashes": [ - "sha256:1972f694c6bc66a2fac8718299e2ab73011d653a6d8059790c3476d2353b99ad", - "sha256:5861f6dc0c16e024cbb0044999f9cf8013b292c05f287df06d3d991a87a4eb89" + "sha256:b409ed0f6913a701ed474a614a3bb46e6953639033e31f769ca7581da5bd1ec1", + "sha256:c254b135fb39ad76e78d4d8f92765ebc9bf92cbc76f49e97ade1d5f5121e1f6f" ], - "version": "==0.12.0" + "version": "==0.12.1" + }, + "jinja2": { + "hashes": [ + "sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd", + "sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4" + ], + "version": "==2.10" + }, + "markupsafe": { + "hashes": [ + "sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665" + ], + "version": "==1.0" + }, + "packaging": { + "hashes": [ + "sha256:e9215d2d2535d3ae866c3d6efc77d5b24a0192cce0ff20e42896cc0664f889c0", + "sha256:f019b770dd64e585a99714f1fd5e01c7a8f11b45635aa953fd41c689a657375b" + ], + "version": "==17.1" }, "parso": { "hashes": [ - "sha256:62bd6bf7f04ab5c817704ff513ef175328676471bdef3629d4bdd46626f75551", - "sha256:a75a304d7090d2c67bd298091c14ef9d3d560e3c53de1c239617889f61d1d307" + "sha256:8105449d86d858e53ce3e0044ede9dd3a395b1c9716c696af8aa3787158ab806", + "sha256:d250235e52e8f9fc5a80cc2a5f804c9fefd886b2e67a2b1099cf085f403f8e33" ], - "version": "==0.2.0" + "version": "==0.3.0" }, "pexpect": { "hashes": [ - "sha256:9783f4644a3ef8528a6f20374eeb434431a650c797ca6d8df0d81e30fffdfa24", - "sha256:9f8eb3277716a01faafaba553d629d3d60a1a624c7cf45daa600d2148c30020c" + "sha256:2a8e88259839571d1251d278476f3eec5db26deb73a70be5ed5dc5435e418aba", + "sha256:3fbd41d4caf27fa4a377bfd16fef87271099463e6fa73e92a52f92dfee5d425b" ], "markers": "sys_platform != 'win32'", - "version": "==4.5.0" + "version": "==4.6.0" }, "pickleshare": { "hashes": [ @@ -551,10 +607,10 @@ }, "ptyprocess": { "hashes": [ - "sha256:e64193f0047ad603b71f202332ab5527c5e52aa7c8b609704fc28c0dc20c4365", - "sha256:e8c43b5eee76b2083a9badde89fd1bbce6c8942d1045146e100b7b5e014f4f1a" + "sha256:923f299cc5ad920c68f2bc0bc98b75b9f838b93b599941a6b63ddbc2476394c0", + "sha256:d7cc528d76e76342423ca640335bd3633420dc1366f258cb31d05e865ef5ca1f" ], - "version": "==0.5.2" + "version": "==0.6.0" }, "pygments": { "hashes": [ @@ -563,6 +619,28 @@ ], "version": "==2.2.0" }, + "pyparsing": { + "hashes": [ + "sha256:0832bcf47acd283788593e7a0f542407bd9550a55a8a8435214a1960e04bcb04", + "sha256:fee43f17a9c4087e7ed1605bd6df994c6173c1e977d7ade7b651292fab2bd010" + ], + "version": "==2.2.0" + }, + "pytz": { + "hashes": [ + "sha256:a061aa0a9e06881eb8b3b2b43f05b9439d6583c206d0a6c340ff72a7b6669053", + "sha256:ffb9ef1de172603304d9d2819af6f5ece76f2e85ec10692a524dd876e72bf277" + ], + "index": "pypi", + "version": "==2018.5" + }, + "requests": { + "hashes": [ + "sha256:63b52e3c866428a224f97cab011de738c36aec0185aa91cfacd418b5d58911d1", + "sha256:ec22d826a36ed72a7358ff3fe56cbd4ba69dd7a6718ffd450ff0e9df7a47ce6a" + ], + "version": "==2.19.1" + }, "simplegeneric": { "hashes": [ "sha256:dc972e06094b9af5b855b3df4a646395e43d1c9d0d39ed345b7393560d0b9173" @@ -576,6 +654,28 @@ ], "version": "==1.11.0" }, + "snowballstemmer": { + "hashes": [ + "sha256:919f26a68b2c17a7634da993d91339e288964f93c274f1343e3bbbe2096e1128", + "sha256:9f3bcd3c401c3e862ec0ebe6d2c069ebc012ce142cce209c098ccb5b09136e89" + ], + "version": "==1.2.1" + }, + "sphinx": { + "hashes": [ + "sha256:85f7e32c8ef07f4ba5aeca728e0f7717bef0789fba8458b8d9c5c294cad134f3", + "sha256:d45480a229edf70d84ca9fae3784162b1bc75ee47e480ffe04a4b7f21a95d76d" + ], + "index": "pypi", + "version": "==1.7.5" + }, + "sphinxcontrib-websupport": { + "hashes": [ + "sha256:68ca7ff70785cbe1e7bccc71a48b5b6d965d79ca50629606c7861a21b206d9dd", + "sha256:9de47f375baf1ea07cdb3436ff39d7a9c76042c10a769c52353ec46e4e8fc3b9" + ], + "version": "==1.1.0" + }, "traitlets": { "hashes": [ "sha256:9c4bd2d267b7153df9152698efb1050a5d84982d3384a37b2c1f7723ba3e7835", @@ -583,6 +683,13 @@ ], "version": "==4.3.2" }, + "urllib3": { + "hashes": [ + "sha256:a68ac5e15e76e7e5dd2b8f94007233e01effe3e50e8daddf69acfd81cb686baf", + "sha256:b5725a0bd4ba422ab0e66e89e030c806576753ea3ee08554382c14e685d117b5" + ], + "version": "==1.23" + }, "wcwidth": { "hashes": [ "sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e", diff --git a/docs/setup.rst b/docs/setup.rst index 046589c40..2dcfeb901 100644 --- a/docs/setup.rst +++ b/docs/setup.rst @@ -39,33 +39,38 @@ or just download the tarball and go that route: Installation & Configuration ---------------------------- -You can go multiple routes with setting up and running Paperless. The `Vagrant -route`_ is quick & easy, but means you're running a VM which comes with memory -consumption etc. We also `support Docker`_, which you can use natively under -Linux and in a VM with `Docker Machine`_ (this guide was written for native -Docker usage under Linux, you might have to adapt it for Docker Machine.) -Not to forget the virtualenv, this is similar to `bare metal`_ with the -exception that you have to activate the virtualenv first. -Last but not least, the standard `bare metal`_ approach is a little more -complicated, but worth it because it makes it easier should you want to -contribute some code back. +You can go multiple routes with setting up and running Paperless: + + * The `bare metal route`_ + * The `vagrant route`_ + * The `docker route`_ + + +The `Vagrant route`_ is quick & easy, but means you're running a VM which comes +with memory consumption, cpu overhead etc. The `docker route`_ offers the same +simplicity as Vagrant with lower resource consumption. + +The `bare metal route`_ is a bit more complicated to setup but makes it easier +should you want to contribute some code back. .. _Vagrant route: setup-installation-vagrant_ -.. _support Docker: setup-installation-docker_ -.. _bare metal: setup-installation-standard_ +.. _docker route: setup-installation-docker_ +.. _bare metal route: setup-installation-bare-metal_ .. _Docker Machine: https://docs.docker.com/machine/ -.. _setup-installation-standard: +.. _setup-installation-bare-metal: Standard (Bare Metal) -..................... ++++++++++++++++++++++ 1. Install the requirements as per the :ref:`requirements ` page. 2. Within the extract of master.zip go to the ``src`` directory. 3. Copy ``../paperless.conf.example`` to ``/etc/paperless.conf`` and open it in - your favourite editor. Because this file contains passwords it should only - be readable by user root and paperless! Set the values for: + your favourite editor. As this file contains passwords. It should only be + readable by user root and paperless! Set the values for: + + Set the values for: * ``PAPERLESS_CONSUMPTION_DIR``: this is where your documents will be dumped to be consumed by Paperless. @@ -82,9 +87,10 @@ Standard (Bare Metal) 6. Start the webserver with ``./manage.py runserver :``. If no specifc IP or port are given, the default is ``127.0.0.1:8000`` also known as http://localhost:8000/. - You should now be able to visit your (empty) at `Paperless webserver`_ or - whatever you chose before. You can login with the user/pass you created in - #5. + You should now be able to visit your (empty) installation at + `Paperless webserver`_ or whatever you chose before. You can login with the + user/pass you created in #5. + 7. In a separate window, change to the ``src`` directory in this repo again, but this time, you should start the consumer script with ``./manage.py document_consumer``. @@ -93,13 +99,18 @@ Standard (Bare Metal) 10. Visit the document list on your webserver, and it should be there, indexed and downloadable. -.. _Paperless webserver: http://127.0.0.1:8000 +.. caution:: + This installation is not secure. Once everything is working head over to + `Making things more permanent`_ + +.. _Paperless webserver: http://127.0.0.1:8000 +.. _Making things more permanent: setup-permanent_ .. _setup-installation-docker: Docker Method -............. ++++++++++++++ 1. Install `Docker`_. @@ -259,7 +270,7 @@ Docker Method .. _setup-installation-vagrant: Vagrant Method -.............. +++++++++++++++ 1. Install `Vagrant`_. How you do that is really between you and your OS. 2. Run ``vagrant up``. An instance will start up for you. When it's ready and @@ -295,6 +306,11 @@ Vagrant Method 11. Visit the document list on your webserver, and it should be there, indexed and downloadable. +.. caution:: + + This installation is not secure. Once everything is working head up to + `Making things more permanent`_ + .. _Vagrant: https://vagrantup.com/ .. _Paperless server: http://172.28.128.4:8000 @@ -304,116 +320,39 @@ Vagrant Method Making Things a Little more Permanent ------------------------------------- -Once you've tested things and are happy with the work flow, you can automate -the process of starting the webserver and consumer automatically. +Once you've tested things and are happy with the work flow, you should secure +the installation and automate the process of starting the webserver and +consumer. -.. _setup-permanent-standard-systemd: - -Standard (Bare Metal, Systemd) -.............................. - -If you're running on a bare metal system that's using Systemd, you can use the -service unit files in the ``scripts`` directory to set this up. You'll need to -create a user called ``paperless`` (without login (if not already done so #5)) -and setup Paperless to be in a place that this new user can read and write to. -Be sure to edit the service scripts to point to the proper location of your -paperless install, referencing the appropriate Python binary. For example: -``ExecStart=/path/to/python3 /path/to/paperless/src/manage.py document_consumer``. -If you don't want to make a new user, you can change the ``Group`` and ``User`` -variables accordingly. - -Then, as ``root`` (or using ``sudo``) you can just copy the ``.service`` files -to the Systemd directory and tell it to enable the two services:: - - # cp /path/to/paperless/scripts/paperless-consumer.service /etc/systemd/system/ - # cp /path/to/paperless/scripts/paperless-webserver.service /etc/systemd/system/ - # systemctl enable paperless-consumer - # systemctl enable paperless-webserver - # systemctl start paperless-consumer - # systemctl start paperless-webserver - - -.. _setup-permanent-standard-ubuntu14: - -Ubuntu 14.04 (Bare Metal, Upstart) -.................................. - -Ubuntu 14.04 and earlier use the `Upstart`_ init system to start services -during the boot process. To configure Upstart to run Paperless automatically -after restarting your system: - -1. Change to the directory where Upstart's configuration files are kept: - ``cd /etc/init`` -2. Create a new file: ``sudo nano paperless-server.conf`` -3. In the newly-created file enter:: - - start on (local-filesystems and net-device-up IFACE=eth0) - stop on shutdown - - respawn - respawn limit 10 5 - - script - exec /srv/paperless/src/manage.py runserver --noreload 0.0.0.0:80 - end script - - Note that you'll need to replace ``/srv/paperless/src/manage.py`` with the - path to the ``manage.py`` script in your installation directory. - - If you are using a network interface other than ``eth0``, you will have to - change ``IFACE=eth0``. For example, if you are connected via WiFi, you will - likely need to replace ``eth0`` above with ``wlan0``. To see all interfaces, - run ``ifconfig -a``. - - Save the file. - -4. Create a new file: ``sudo nano paperless-consumer.conf`` - -5. In the newly-created file enter:: - - start on (local-filesystems and net-device-up IFACE=eth0) - stop on shutdown - - respawn - respawn limit 10 5 - - script - exec /srv/paperless/src/manage.py document_consumer - end script - - Replace ``/srv/paperless/src/manage.py`` with the same values as in step 3 - above and replace ``eth0`` with the appropriate value, if necessary. Save the - file. - -These two configuration files together will start both the Paperless webserver -and document consumer processes when the file system and network interface -specified is available after boot. Furthermore, if either process ever exits -unexpectedly, Upstart will try to restart it a maximum of 10 times within a 5 -second period. - -.. _Upstart: http://upstart.ubuntu.com/ - - -.. _setup-permanent-vagrant: - +.. _setup-permanent-webserver: Using a Real Webserver -...................... +++++++++++++++++++++++ The default is to use Django's development server, as that's easy and does the -job well enough on a home network. However, if you want to do things right, -it's probably a good idea to use a webserver capable of handling more than one -thread. You will also have to let the webserver serve the static files (CSS, -JavaScript) from the directory configured in ``PAPERLESS_STATICDIR``. For that, -you need to run ``./manage.py collectstatic`` in the ``src`` directory. The -default static files directory is ``../static``. +job well enough on a home network. However it is heavily discouraged to use +it for more than that. + +If you want to do things right you should use a real webserver capable of +handling more than one thread. You will also have to let the webserver serve +the static files (CSS, JavaScript) from the directory configured in +``PAPERLESS_STATICDIR``. The default static files directory is ``../static``. + +For that you need to activate your virtual environment and collect the static +files with the command: + +.. code:: bash + + $ cd /src + $ ./manage.py collectstatic + Apache ~~~~~~ This is a configuration supplied by `steckerhalter`_ on GitHub. It uses Apache -and mod_wsgi, with a Paperless installation in /home/paperless/: +and mod_wsgi, with a Paperless installation in ``/home/paperless/``: .. code:: apache @@ -444,170 +383,150 @@ Nginx + Gunicorn If you're using Nginx, the most common setup is to combine it with a Python-based server like Gunicorn so that Nginx is acting as a proxy. Below is -a copy of a simple Nginx configuration fragment making use of SSL and IPv6 to -refer to a gunicorn instance listening on a local Unix socket: +a copy of a simple Nginx configuration fragment making use of a gunicorn +instance listening on localhost port 8000. .. code:: nginx - upstream transfer_server { - server unix:/run/example.com/gunicorn.sock fail_timeout=0; - } - - # Redirect requests on port 80 to 443 server { - listen 80; - listen [::]:80; - server_name example.com; - rewrite ^ https://$server_name$request_uri? permanent; + listen 80; + + index index.html index.htm index.php; + access_log /var/log/nginx/paperless_access.log; + error_log /var/log/nginx/paperless_error.log; + + location /static { + + autoindex on; + alias + + } + + location / { + + proxy_set_header Host $http_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-Proto $scheme; + + proxy_pass http://127.0.0.1:8000 + } } - server { - listen 443 ssl; - listen [::]:443; - client_max_body_size 4G; - server_name example.com; - keepalive_timeout 5; - root /var/www/example.com; +The gunicorn server can be started with the command: - ssl on; +.. code-block:: shell - ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; - ssl_trusted_certificate /etc/letsencrypt/live/example.com/fullchain.pem; - ssl_session_timeout 1d; - ssl_session_cache shared:SSL:50m; + $ /bin/gunicorn /src/paperless.wsgi -w 2 - # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits - # Generate with: - # openssl dhparam -out /etc/nginx/dhparam.pem 2048 - ssl_dhparam /etc/nginx/dhparam.pem; - # What Mozilla calls "Intermediate configuration" - # Copied from https://mozilla.github.io/server-side-tls/ssl-config-generator/ - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; - ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS'; - ssl_prefer_server_ciphers on; +.. _setup-permanent-standard-systemd: - add_header Strict-Transport-Security max-age=15768000; +Standard (Bare Metal + Systemd) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - ssl_stapling on; - ssl_stapling_verify on; +If you're running on a bare metal system that's using Systemd, you can use the +service unit files in the ``scripts`` directory to set this up. - access_log /var/log/nginx/example.com.log main; - error_log /var/log/nginx/example.com.err info; +1. You'll need to create a group and user called ``paperless`` (without login) +2. Setup Paperless to be in a place that this new user can read and write to. +3. Ensure ``/etc/paperless`` is readable by the ``paperless`` user. +4. Copy the service file from the ``scripts`` directory to + ``/etc/systemd/system``. - location / { - try_files $uri @proxy_to_app; - } +.. code-block:: bash - location @proxy_to_app { - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto https; - proxy_set_header Host $host; - proxy_redirect off; - proxy_pass http://transfer_server; - } + $ cp /path/to/paperless/scripts/paperless-consumer.service /etc/systemd/system/ + $ cp /path/to/paperless/scripts/paperless-webserver.service /etc/systemd/system/ - } +5. Edit the service file to point the ``ExecStart`` line to the proper location + of your paperless install, referencing the appropriate Python binary. For + example: + ``ExecStart=/path/to/python3 /path/to/paperless/src/manage.py document_consumer``. +6. Start and enable (so they start on boot) the services. -Once you've got Nginx configured, you'll want to have a configuration file for -your gunicorn instance. This should do the trick: +.. code-block:: bash -.. code:: python + $ systemctl enable paperless-consumer + $ systemctl enable paperless-webserver + $ systemctl start paperless-consumer + $ systemctl start paperless-webserver - import os - bind = 'unix:/run/example.com/gunicorn.sock' - backlog = 2048 - workers = 6 - worker_class = 'sync' - worker_connections = 1000 - timeout = 30 - keepalive = 2 - debug = False - spew = False - daemon = False - pidfile = None - umask = 0 - user = None - group = None - tmp_upload_dir = None - errorlog = '/var/log/example.com/gunicorn.err' - loglevel = 'warning' - accesslog = '/var/log/example.com/gunicorn.log' - proc_name = None +.. _setup-permanent-standard-upstart: - def post_fork(server, worker): - server.log.info("Worker spawned (pid: %s)", worker.pid) +Standard (Bare Metal + Upstart) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - def pre_fork(server, worker): - pass +Ubuntu 14.04 and earlier use the `Upstart`_ init system to start services +during the boot process. To configure Upstart to run Paperless automatically +after restarting your system: - def pre_exec(server): - server.log.info("Forked child, re-executing.") +1. Change to the directory where Upstart's configuration files are kept: + ``cd /etc/init`` +2. Create a new file: ``sudo nano paperless-server.conf`` +3. In the newly-created file enter:: - def when_ready(server): - server.log.info("Server is ready. Spawning workers") + start on (local-filesystems and net-device-up IFACE=eth0) + stop on shutdown - def worker_int(worker): - worker.log.info("worker received INT or QUIT signal") + respawn + respawn limit 10 5 - ## get traceback info - import threading, sys, traceback - id2name = dict([(th.ident, th.name) for th in threading.enumerate()]) - code = [] - for threadId, stack in sys._current_frames().items(): - code.append("\n# Thread: %s(%d)" % (id2name.get(threadId,""), - threadId)) - for filename, lineno, name, line in traceback.extract_stack(stack): - code.append('File: "%s", line %d, in %s' % (filename, - lineno, name)) - if line: - code.append(" %s" % (line.strip())) - worker.log.debug("\n".join(code)) + script + exec /bin/gunicorn /src/paperless.wsgi -w 2 + end script + + Note that you'll need to replace ``/srv/paperless/src/manage.py`` with the + path to the ``manage.py`` script in your installation directory. + + If you are using a network interface other than ``eth0``, you will have to + change ``IFACE=eth0``. For example, if you are connected via WiFi, you will + likely need to replace ``eth0`` above with ``wlan0``. To see all interfaces, + run ``ifconfig -a``. + + Save the file. + +4. Create a new file: ``sudo nano paperless-consumer.conf`` + +5. In the newly-created file enter:: + + start on (local-filesystems and net-device-up IFACE=eth0) + stop on shutdown + + respawn + respawn limit 10 5 + + script + exec /bin/python /manage.py document_consumer + end script + + Replace the path placeholder and ``eth0`` with the appropriate value and save the file. + +These two configuration files together will start both the Paperless webserver +and document consumer processes when the file system and network interface +specified is available after boot. Furthermore, if either process ever exits +unexpectedly, Upstart will try to restart it a maximum of 10 times within a 5 +second period. + +.. _Upstart: http://upstart.ubuntu.com/ - def worker_abort(worker): - worker.log.info("worker received SIGABRT signal") Vagrant -....... +~~~~~~~ You may use the Ubuntu explanation above. Replace ``(local-filesystems and net-device-up IFACE=eth0)`` with ``vagrant-mounted``. + .. _setup-permanent-docker: Docker -...... +~~~~~~ If you're using Docker, you can set a restart-policy_ in the ``docker-compose.yml`` to have the containers automatically start with the Docker daemon. .. _restart-policy: https://docs.docker.com/engine/reference/commandline/run/#restart-policies-restart - - -.. _setup-subdirectory: - -Hosting Paperless in a Subdirectory ------------------------------------ - -Paperless was designed to run off the root of the hosting domain, -(ie: ``https://example.com/``) but with a few changes, you can configure -it to run in a subdirectory on your server -(ie: ``https://example.com/paperless/``). - -Thanks to the efforts of `maphy-psd`_ on `Github`_, running Paperless in a -subdirectory is now as easy as setting a config variable. Simply set -``PAPERLESS_FORCE_SCRIPT_NAME`` in your environment or -``/etc/paperless.conf`` to the path you want Paperless hosted at, configure -Nginx/Apache for your needs and you're done. So, if you want Paperless to live -at ``https://example.com/arbitrary/path/to/paperless`` then you just set -``PAPERLESS_FORCE_SCRIPT_NAME`` to ``/arbitrary/path/to/paperless``. Note the -leading ``/`` there. - -As to how to configure Nginx or Apache for this, that's on you :-) - -.. _maphy-psd: https://github.com/maphy-psd -.. _Github: https://github.com/danielquinn/paperless/pull/255 diff --git a/scripts/paperless-webserver.service b/scripts/paperless-webserver.service index b4eb53dd0..6bc986cdd 100644 --- a/scripts/paperless-webserver.service +++ b/scripts/paperless-webserver.service @@ -4,7 +4,7 @@ Description=Paperless webserver [Service] User=paperless Group=paperless -ExecStart=/home/paperless/project/virtualenv/bin/python /home/paperless/project/src/manage.py runserver --noreload 0.0.0.0:8000 +ExecStart=/home/paperless/project/virtualenv/bin/gunicorn /home/paperless/project/src/paperless.wsgi -w 2 [Install] WantedBy=multi-user.target