From 6fd9995aa1bc12f8c5d2ef1211dee0c1e6398c95 Mon Sep 17 00:00:00 2001 From: Ovv Date: Tue, 24 Apr 2018 22:19:37 +0200 Subject: [PATCH 01/11] Installation documentation setup Issue #329 --- Pipfile | 1 + Pipfile.lock | 141 ++++++++- docs/setup.rst | 427 +++++++++++----------------- scripts/paperless-webserver.service | 2 +- 4 files changed, 308 insertions(+), 263 deletions(-) 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..0f41ddf03 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "928fbb4c8952128aef7a2ed2707ce510d31d49df96cfc5f08959698edff6e67f" + "sha256": "70653513e6c80b7e07f8e7fbff7592f2d22749dc5b1d723a04f921242bc9a78f" }, "pipfile-spec": 6, "requires": {}, @@ -30,10 +30,10 @@ }, "certifi": { "hashes": [ - "sha256:14131608ad2fd56836d33a71ee60fa1c82bc9d2c8d98b7bdbc631fe1b3cd1296", - "sha256:edbc3f203427eef571f79a7692bb160a2b0f7ccaa31953e99bd17e307cf63f7d" + "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7", + "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0" ], - "version": "==2018.1.18" + "version": "==2018.4.16" }, "chardet": { "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": [ @@ -292,7 +292,6 @@ }, "pluggy": { "hashes": [ - "sha256:714306e9b9a7b24ee4c1e3ff6463d7f652cdd30f4693121b31572e2fe1fdaea3", "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff", "sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c", "sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5" @@ -483,6 +482,20 @@ } }, "develop": { + "alabaster": { + "hashes": [ + "sha256:2eef172f44e8d301d25aff8068fddd65f767a3f04b5f15b0f4922f113aa1c732", + "sha256:37cdcb9e9954ed60912ebc1ca12a9d12178c26637abdf124e3cde2341c257fe0" + ], + "version": "==0.7.10" + }, + "babel": { + "hashes": [ + "sha256:8ce4cb6fdd4393edd323227cba3a077bceb2a6ce5201c902c65e730046f41f14", + "sha256:ad209a68d7162c4cff4b29cdebe3dec4cef75492df501b0049a9433c96ce6f80" + ], + "version": "==2.5.3" + }, "backcall": { "hashes": [ "sha256:38ecd85be2c1e78f77fd91700c76e14667dc21e2713b63876c0eb901196e01e4", @@ -490,6 +503,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,6 +524,28 @@ ], "version": "==4.3.0" }, + "docutils": { + "hashes": [ + "sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6", + "sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274", + "sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6" + ], + "version": "==0.14" + }, + "idna": { + "hashes": [ + "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f", + "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4" + ], + "version": "==2.6" + }, + "imagesize": { + "hashes": [ + "sha256:3620cc0cadba3f7475f9940d22431fc4d407269f1be59ec9b8edcca26440cf18", + "sha256:5b326e4678b6925158ccc66a9fa3122b6106d7c876ee32d7de6ce59385b96315" + ], + "version": "==1.0.0" + }, "ipython": { "hashes": [ "sha256:85882f97d75122ff8cdfe129215a408085a26039527110c8d4a2b8a5e45b7639", @@ -519,6 +568,26 @@ ], "version": "==0.12.0" }, + "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", @@ -563,6 +632,33 @@ ], "version": "==2.2.0" }, + "pyparsing": { + "hashes": [ + "sha256:0832bcf47acd283788593e7a0f542407bd9550a55a8a8435214a1960e04bcb04", + "sha256:281683241b25fe9b80ec9d66017485f6deff1af5cde372469134b56ca8447a07", + "sha256:8f1e18d3fd36c6795bb7e02a39fd05c611ffc2596c1e0d995d34d67630426c18", + "sha256:9e8143a3e15c13713506886badd96ca4b579a87fbdf49e550dbfc057d6cb218e", + "sha256:b8b3117ed9bdf45e14dcc89345ce638ec7e0e29b2b579fa1ecf32ce45ebac8a5", + "sha256:e4d45427c6e20a59bf4f88c639dcc03ce30d193112047f94012102f235853a58", + "sha256:fee43f17a9c4087e7ed1605bd6df994c6173c1e977d7ade7b651292fab2bd010" + ], + "version": "==2.2.0" + }, + "pytz": { + "hashes": [ + "sha256:65ae0c8101309c45772196b21b74c46b2e5d11b6275c45d251b150d5da334555", + "sha256:c06425302f2cf668f1bba7a0a03f3c1d34d4ebeef2c72003da308b3947c7f749" + ], + "index": "pypi", + "version": "==2018.4" + }, + "requests": { + "hashes": [ + "sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b", + "sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e" + ], + "version": "==2.18.4" + }, "simplegeneric": { "hashes": [ "sha256:dc972e06094b9af5b855b3df4a646395e43d1c9d0d39ed345b7393560d0b9173" @@ -576,6 +672,28 @@ ], "version": "==1.11.0" }, + "snowballstemmer": { + "hashes": [ + "sha256:919f26a68b2c17a7634da993d91339e288964f93c274f1343e3bbbe2096e1128", + "sha256:9f3bcd3c401c3e862ec0ebe6d2c069ebc012ce142cce209c098ccb5b09136e89" + ], + "version": "==1.2.1" + }, + "sphinx": { + "hashes": [ + "sha256:3aded1a355f662547b8a948131f3faecbc3dea8951847fe0ee4c59689f8220b2", + "sha256:9495a1f78c13d0a725ab8104e923e9663519ecc04552aa4a8f684c2da355443d" + ], + "index": "pypi", + "version": "==1.7.3" + }, + "sphinxcontrib-websupport": { + "hashes": [ + "sha256:7a85961326aa3a400cd4ad3c816d70ed6f7c740acd7ce5d78cd0a67825072eb9", + "sha256:f4932e95869599b89bf4f80fc3989132d83c9faa5bf633e7b5e0c25dffb75da2" + ], + "version": "==1.0.1" + }, "traitlets": { "hashes": [ "sha256:9c4bd2d267b7153df9152698efb1050a5d84982d3384a37b2c1f7723ba3e7835", @@ -583,6 +701,13 @@ ], "version": "==4.3.2" }, + "urllib3": { + "hashes": [ + "sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b", + "sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f" + ], + "version": "==1.22" + }, "wcwidth": { "hashes": [ "sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e", diff --git a/docs/setup.rst b/docs/setup.rst index 1467fb2c9..5155eda22 100644 --- a/docs/setup.rst +++ b/docs/setup.rst @@ -39,34 +39,39 @@ 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: -.. _Vagrant route: setup-installation-vagrant_ -.. _support Docker: setup-installation-docker_ -.. _bare metal: setup-installation-standard_ + * 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`_ offer the same +simplicity a vagrant with less ressources consumption. Only the native usage +under linux is documented you will need to adapt the documentation when using +`Docker machine`_. + +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_ +.. _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`` also the virtual - envrionment look there for it 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: +3. Copy ``../paperless.conf.example`` to ``/etc/paperless.conf``. This file + contains passwords it should only be readable by user root and paperless ! + + Set the values for: * ``PAPERLESS_CONSUMPTION_DIR``: this is where your documents will be dumped to be consumed by Paperless. @@ -81,9 +86,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 + 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``. @@ -92,13 +98,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 up 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`_. @@ -257,7 +268,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 @@ -292,125 +303,50 @@ 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 - .. _setup-permanent: 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-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 +file 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 @@ -439,136 +375,145 @@ and mod_wsgi, with a Paperless installation in /home/paperless/: 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: +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 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-subdirectory: - add_header Strict-Transport-Security max-age=15768000; +Consumer +++++++++ - ssl_stapling on; - ssl_stapling_verify on; +Once you've tested things and are happy with the work flow, you can automate +the process of starting the webserver and consumer automatically. - access_log /var/log/nginx/example.com.log main; - error_log /var/log/nginx/example.com.err info; +.. _setup-permanent-standard-systemd: - location / { - try_files $uri @proxy_to_app; - } +Standard (Bare Metal + Systemd) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - 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; - } +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. - } +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``. -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 + $ cp /path/to/paperless/scripts/paperless-consumer.service /etc/systemd/system/ + $ cp /path/to/paperless/scripts/paperless-webserver.service /etc/systemd/system/ - import os +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 - 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 +.. code-block:: bash - def post_fork(server, worker): - server.log.info("Worker spawned (pid: %s)", worker.pid) + $ systemctl enable paperless-consumer + $ systemctl enable paperless-webserver + $ systemctl start paperless-consumer + $ systemctl start paperless-webserver - def pre_fork(server, worker): - pass +.. _setup-permanent-vagrant: - def pre_exec(server): - server.log.info("Forked child, re-executing.") - def when_ready(server): - server.log.info("Server is ready. Spawning workers") +Standard (Bare Metal + Upstart) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - def worker_int(worker): - worker.log.info("worker received INT or QUIT signal") +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: - ## 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)) +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 worker_abort(worker): - worker.log.info("worker received SIGABRT signal") + start on (local-filesystems and net-device-up IFACE=eth0) + stop on shutdown + + respawn + respawn limit 10 5 + + 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/ Vagrant -....... +~~~~~~~ You may use the Ubuntu explanation above. Replace ``(local-filesystems and net-device-up IFACE=eth0)`` with ``vagrant-mounted``. @@ -576,35 +521,9 @@ You may use the Ubuntu explanation above. Replace .. _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. +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 +.. _restart-policy: https://docs.docker.com/engine/reference/commandline/run/#restart-policies-restart \ No newline at end of file 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 From 5db49a37100791a9356699cf7a25000c7085da08 Mon Sep 17 00:00:00 2001 From: Enno Lohmeier Date: Wed, 4 Jul 2018 13:00:28 +0200 Subject: [PATCH 02/11] add search field on admin start page and module start page --- src/documents/templates/admin/index.html | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/documents/templates/admin/index.html b/src/documents/templates/admin/index.html index 67c7dbeb1..410c9e684 100644 --- a/src/documents/templates/admin/index.html +++ b/src/documents/templates/admin/index.html @@ -4,6 +4,24 @@ {% load i18n static %} +{# This block adds a search form on the admin start page and on the module start page so that #} +{# the user can quickly search for documents #} +{% block pretitle %} +
+

{% trans 'Search documents' %}

+ +
+
+
+{% endblock %} + + {# This whole block is here just to override the `get_admin_log` line so #} {# that the log entries aren't limited to the current user #} {% block sidebar %} From 619878b2f600db024eef33ef0a94a9c2ebde3fd0 Mon Sep 17 00:00:00 2001 From: Enno Lohmeier Date: Thu, 5 Jul 2018 12:56:20 +0200 Subject: [PATCH 03/11] add document count column for tags and correspondents --- src/documents/admin.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/documents/admin.py b/src/documents/admin.py index 39524ae21..2727c7704 100644 --- a/src/documents/admin.py +++ b/src/documents/admin.py @@ -105,17 +105,23 @@ class CommonAdmin(admin.ModelAdmin): class CorrespondentAdmin(CommonAdmin): - list_display = ("name", "match", "matching_algorithm") + list_display = ("name", "match", "matching_algorithm", "document_count") list_filter = ("matching_algorithm",) list_editable = ("match", "matching_algorithm") + def document_count(self, obj): + return obj.documents.count() + class TagAdmin(CommonAdmin): - list_display = ("name", "colour", "match", "matching_algorithm") + list_display = ("name", "colour", "match", "matching_algorithm", "document_count") list_filter = ("colour", "matching_algorithm") list_editable = ("colour", "match", "matching_algorithm") + def document_count(self, obj): + return obj.documents.count() + class DocumentAdmin(CommonAdmin): From f31d535da83b36bcfe075dc3f04c62f321d8cb7e Mon Sep 17 00:00:00 2001 From: Enno Lohmeier Date: Thu, 5 Jul 2018 12:56:37 +0200 Subject: [PATCH 04/11] optimize Dockerfile for caching --- Dockerfile | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 7295bc5c0..f02bf3336 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,11 +4,8 @@ LABEL maintainer="The Paperless Project https://github.com/danielquinn/paperless contributors="Guy Addadi , Pit Kleyersburg , \ Sven Fischer " -# Copy application +# Copy requirements file and init script COPY requirements.txt /usr/src/paperless/ -COPY src/ /usr/src/paperless/src/ -COPY data/ /usr/src/paperless/data/ -COPY media/ /usr/src/paperless/media/ COPY scripts/docker-entrypoint.sh /sbin/docker-entrypoint.sh # Set export and consumption directories @@ -44,3 +41,8 @@ VOLUME ["/usr/src/paperless/data", "/usr/src/paperless/media", "/consume", "/exp ENTRYPOINT ["/sbin/docker-entrypoint.sh"] CMD ["--help"] +# Copy application +COPY src/ /usr/src/paperless/src/ +COPY data/ /usr/src/paperless/data/ +COPY media/ /usr/src/paperless/media/ + From 2894d105cbb963d3889750d3af0e6cbec9b04c27 Mon Sep 17 00:00:00 2001 From: Enno Lohmeier Date: Thu, 5 Jul 2018 13:10:08 +0200 Subject: [PATCH 05/11] fix code style issue --- src/documents/admin.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/documents/admin.py b/src/documents/admin.py index 2727c7704..659ad8581 100644 --- a/src/documents/admin.py +++ b/src/documents/admin.py @@ -115,7 +115,8 @@ class CorrespondentAdmin(CommonAdmin): class TagAdmin(CommonAdmin): - list_display = ("name", "colour", "match", "matching_algorithm", "document_count") + list_display = ("name", "colour", "match", "matching_algorithm", + "document_count") list_filter = ("colour", "matching_algorithm") list_editable = ("colour", "match", "matching_algorithm") From 826db170d374b24f9411f70232fcc9bc65110f8d Mon Sep 17 00:00:00 2001 From: Sven Fischer Date: Sun, 8 Jul 2018 16:20:07 +0200 Subject: [PATCH 06/11] minor updates to :de: Readme --- README-de.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/README-de.md b/README-de.md index ffd65ef9a..58ed1d60b 100644 --- a/README-de.md +++ b/README-de.md @@ -3,11 +3,11 @@ # Paperless -[![Documentation](https://readthedocs.org/projects/paperless/badge/?version=latest)](https://paperless.readthedocs.org/) [![Chat](https://badges.gitter.im/danielquinn/paperless.svg)](https://gitter.im/danielquinn/paperless) [![Travis](https://travis-ci.org/danielquinn/paperless.svg?branch=master)](https://travis-ci.org/danielquinn/paperless) [![Coverage Status](https://coveralls.io/repos/github/danielquinn/paperless/badge.svg?branch=master)](https://coveralls.io/github/danielquinn/paperless?branch=master) [![Thanks](https://img.shields.io/badge/THANKS-md-ff69b4.svg)](https://github.com/danielquinn/paperless/blob/master/THANKS.md) +[![Dokumentation](https://readthedocs.org/projects/paperless/badge/?version=latest)](https://paperless.readthedocs.org/) [![Chat](https://badges.gitter.im/danielquinn/paperless.svg)](https://gitter.im/danielquinn/paperless) [![Travis](https://travis-ci.org/danielquinn/paperless.svg?branch=master)](https://travis-ci.org/danielquinn/paperless) [![Coverage Status](https://coveralls.io/repos/github/danielquinn/paperless/badge.svg?branch=master)](https://coveralls.io/github/danielquinn/paperless?branch=master) [![Danke](https://img.shields.io/badge/THANKS-md-ff69b4.svg)](https://github.com/danielquinn/paperless/blob/master/THANKS.md) Indexiere und archiviere alle deine eingescannten Papierdokumente -Ich hasse Papier. Abgesehen von Umweltproblemen, ist es der Albtraum einer technisch-interessierten Person: +Ich hasse Papier. Abgesehen von Umweltproblemen, ist es der Albtraum einer technisch-interessierten Person: * Es gibt keine Suchfunktion * Es braucht physischen Platz @@ -22,8 +22,8 @@ In den vergangenen Monaten hatte ich mehrmals das Problem, das richtige Dokument Paperless steuert nicht deinen Scanner, es hilft nur damit umzugehen, was der Scanner herausspuckt 1. Kaufe einen Dokumentenscanner, der an einen Ort in deinem Netzwerk schreiben kann. Wenn du Inspirationen brauchst, schau in die [Scannerempfehlungen](https://paperless.readthedocs.io/en/latest/scanners.html). -2. Stelle "Scanne zu FTP" oder ähnliches ein. Es sollte möglich sein, eingescannte Bilder ohne etwas tun zu müssen an einen Server hochzuladen. Natürlich kannst du auch die einscannte Datei händisch hochladen, wenn der Scanner automatisches Hochladen nicht unterstützt. Paperless ist es egal, wie die Dokumente in seinen lokalen Konsum-Ordner gelangen. -3. Besitze einen Zielserver, lasse das Papierless-Konsum-Skript laufen, um die Datei mit OCR zu versehen und sie in einer lokalen Datenbank zu indexieren. +2. Stelle "Scanne zu FTP" oder ähnliches ein. Es sollte möglich sein, eingescannte Bilder ohne etwas tun zu müssen an einen Server hochzuladen. Natürlich kannst du auch die einscannte Datei händisch hochladen, wenn der Scanner automatisches Hochladen nicht unterstützt. Paperless ist es egal, wie die Dokumente in seinen lokalen Konsumordner gelangen. +3. Besitze einen Zielserver, lasse das Papierless-Konsumskript laufen, um die Datei mit OCR zu versehen und sie in einer lokalen Datenbank zu indexieren. 4. Benutze die Weboberfläche, um die Datenbank zu durchforsten und zu finden, was du suchst. 5. Lade die PDF-Datei, die du brauchst/möchtest über die Weboberfläche herunter und mach was auch immer du willst damit. Du kannst es auch drucken und versenden, so als wäre es das Original. In den meisten Fällen, wird das niemanden interessieren oder bemerken. @@ -32,14 +32,14 @@ Hier das, was du bekommt: ![Vorher und Nachher](https://raw.githubusercontent.com/danielquinn/paperless/master/docs/_static/screenshot.png) -## Dokcumentation +## Dokumentation Diese ist komplett verfügbar auf [ReadTheDocs](https://paperless.readthedocs.org/). ## Anforderungen -Dies alles ist ein wirklich ziemlich einfacher, glänzender und benutzerfreundlicher Wrapper rund um einige sehr mächtige Werkzeuge. +Dies alles ist eine wirklich ziemlich einfache, glänzende und benutzerfreundliche Hülle rund um einige sehr mächtige Werkzeuge. * [ImageMagick](http://imagemagick.org/) wandelt Bilder zwischen Farbe und Graustufen um. * [Tesseract](https://github.com/tesseract-ocr) erledigt die Buchstabenerkennung. @@ -49,36 +49,36 @@ Dies alles ist ein wirklich ziemlich einfacher, glänzender und benutzerfreundli * [Pillow](https://pypi.python.org/pypi/pillowfight/) lädt die Bilddaten als Python-Objekt, um sie mit PyOCR zu verwenden. * [PyOCR](https://github.com/jflesch/pyocr) ist ein glatter, programmatischer Wrapper um Tesseract. * [Django](https://www.djangoproject.com/) ist das Framework, auf das dieses Projekt aufbaut. - * [Python-GNUPG](http://pythonhosted.org/python-gnupg/) entschlüsselt die PDFs auf Abruf, um das Herunterladen unverschlüsselte Dateien zu ermöglichen, während die verschlüsselten Datein auf der Festplatte bleiben. + * [Python-GNUPG](http://pythonhosted.org/python-gnupg/) entschlüsselt die PDFs auf Abruf, um das Herunterladen unverschlüsselter Dateien zu ermöglichen, während die verschlüsselten Dateien auf der Festplatte bleiben. ## Status des Projekts -Dieses Projekt wurde um 2015 gestarten, und es gibt viele Leute, die es verwenden. Warum auch immer ist es ziemlich beliebt in Deutschland -- vielleicht kann jemand dort trüben mich über das Warum? aufklären. +Dieses Projekt wurde um 2015 gestartet und es gibt viele Leute, die es verwenden. Warum auch immer ist es ziemlich beliebt in Deutschland -- vielleicht kann jemand dort drüben mich über das Warum aufklären. -Ich entwickle keine neuen Funktionen mehr an Paperless, weil es genau das tut, was ich brauche und meine Aufmerksamkeit meinem neuesten Projekt [Aletheia](https://github.com/danielquinn/aletheia) gewidmet habe. Ich verlasse jedoch nicht das Projekt. Ich bin glücklich damit, Pull Requests zu begutachten und Fragen im Issue-Bereich zu beantworten. Wenn du ein Entwickler bist und eine neue Funktion willst, reihe sie in den Issues ein und/oder sende einen PR! Ich bin glücklich damit, neue Sachen hinzuzufügen, habe aber einfach nicht die Zeit, sie selbst zu erarbeiten. +Ich entwickle keine neuen Funktionen mehr für Paperless, weil es genau das tut, was ich brauche und meine Aufmerksamkeit meinem neuesten Projekt [Aletheia](https://github.com/danielquinn/aletheia) gewidmet ist. Ich verlasse jedoch nicht das Projekt. Ich bin glücklich damit, Pull Requests zu begutachten und Fragen im Issue-Bereich zu beantworten. Wenn du ein Entwickler bist und eine neue Funktion willst, reihe sie in den Issues ein und/oder sende einen PR! Ich bin glücklich damit, neue Sachen hinzuzufügen, habe aber einfach nicht die Zeit, sie selbst zu erarbeiten. ## Verknüpfte Prjekte -Paperless gibt es bereits seit einer Weile und Leute haben damit angefangen, Sachen rund um Paperless zu entwicklen. Wenn du einer dieser Menschen bist, kannst du dein Porjekt zu dieser Liste hinzufügen: +Paperless gibt es bereits seit einer Weile und Leute haben damit angefangen, Sachen rund um Paperless zu entwickeln. Wenn du einer dieser Menschen bist, kannst du dein Projekt zu dieser Liste hinzufügen: -* [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 Desktop](https://github.com/thomasbrueggemann/paperless-desktop): Eine Desktop-Oberfläche für deine Paperless-Installation. Läuft auf Mac, Linux und Windows. +* [ansible-role-paperless](https://github.com/ovv/ansible-role-paperless): Eine einfache Möglichkeit, Paperless via Ansible laufen zu lassen. ## Ähnliche Projekte -Es gibt da draußen auch das Projekt [Mayan EDMS](https://mayan.readthedocs.org/en/latest/), welches überraschenderweise sehr große überschneidende Techniken hat wie Paperless. Mayan EDMS ist *viel* funktionsreicher und kommt ebenso mit einer glatten UI, aber kommt noch mit Python2; basiert jedoch auch auf Django und verwendet ein Konsum-Modell mit Tesseract und Unpaper. Es kann sein, dass Paperless weniger Ressourcen verbraucht, aber um ehrlich zu sein, hab ich das noch nicht meiner selbst getestet. Eine Sache jedoch ist klat, *Paperless* ist ein **viel** besserer Name. +Es gibt da draußen auch das Projekt [Mayan EDMS](https://mayan.readthedocs.org/en/latest/), welches überraschenderweise sehr große überschneidende Techniken hat wie Paperless. Mayan EDMS ist *viel* funktionsreicher und kommt ebenso mit einer glatten UI, aber kommt noch mit Python2; basiert jedoch auch auf Django und verwendet ein Konsummodell mit Tesseract und Unpaper. Es kann sein, dass Paperless weniger Ressourcen verbraucht, aber um ehrlich zu sein, hab ich das noch nicht selbst getestet. Eine Sache jedoch ist klar, *Paperless* ist ein **viel** besserer Name. ## Wichtiger Hinweis -Dokumentenscanner werden typerweise verwendet, um sensible Dokumente zu scannen. Dinge wie die Sozialversicherungsnummer, Steueraufzeichnungen, Rechnungen, etc. Während Paperless die Originaldateien über das Konsum-Skript verschlüsselt, sind die OCR-Texte *nicht* verschlüsselt und demnach in Klartext gespeichert (es muss durchsuchbar sein, also wenn jemand eine Idee hat, wie man das mit verschlüsselten Daten tun kann: Ich bin ganz Ohr). Das bedeutet, dass Paperless niemals auf einem unvertrauten Host laufen sollte. Stattdessen empfehle ich, wenn du es verwenden willst, es lokal auf einem Server in deinem Zuhause laufen zu lassen. +Dokumentenscanner werden typerweise verwendet, um sensible Dokumente zu scannen. Dinge wie die Sozialversicherungsnummer, Steueraufzeichnungen, Rechnungen, etc. Während Paperless die Originaldateien über das Konsumskript verschlüsselt, sind die OCR-Texte *nicht* verschlüsselt und demnach in Klartext gespeichert (es muss durchsuchbar sein, also wenn jemand eine Idee hat, wie man das mit verschlüsselten Daten tun kann: Ich bin ganz Ohr). Das bedeutet, dass Paperless niemals auf einem nicht vertrauten Host laufen sollte. Stattdessen empfehle ich, wenn du es verwenden willst, es lokal auf einem Server in deinem Zuhause laufen zu lassen. ## Spenden -Wie mit aller Freier Software, liegt die Macht weniger in den Finanzen als mehr in den gemeinsamen Bemühungen. Ich schätze wirklich jeden Pull Request und Bugreport, der von Benutzetn von Paperless getätigt wird, als bitte macht damit weiter. Wenn du jedoch nicht einer für Programmieren/Design/Dokumentation bist und mich wirklich finanziell unterstützen willst, sage ich nicht nein dazu ;-) +Wie mit aller Freier Software, liegt die Macht weniger in den Finanzen als mehr in den gemeinsamen Bemühungen. Ich schätze wirklich jeden Pull Request und Bugreport, der von Benutzern von Paperless getätigt wird, also bitte macht damit weiter. Wenn du jedoch nicht einer für Programmieren/Design/Dokumentation bist und mich wirklich finanziell unterstützen willst, sage ich nicht nein dazu ;-) -Das Ding ist, mir geht es finanziell OK, also bitte ich darum, würde ich darum bitten, an den [Hochkommissar der Vereinten Nationen für Flüchtlinge](https://donate.unhcr.org/int-en/general) zu spenden. Diese machen wichtige Arbeit und brauchen das Geld viel dringender als ich. +Das Ding ist, mir geht es finanziell OK, also würde ich dich darum bitten, an den [Hochkommissar der Vereinten Nationen für Flüchtlinge](https://donate.unhcr.org/int-en/general) zu spenden. Diese machen wichtige Arbeit und brauchen das Geld viel dringender als ich. From ba1f437e0b06730b6dd256a19bc1fae6b9c82715 Mon Sep 17 00:00:00 2001 From: Daniel Quinn Date: Sun, 8 Jul 2018 16:05:16 +0100 Subject: [PATCH 07/11] Add changelog notes for all of Enno's contributions --- docs/changelog.rst | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index de2e237d9..f3442fe9a 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,20 @@ Changelog ######### +2.1.0 +===== + +* `Enno Lohmeier`_ added three simple features that make Paperless a lot more + user (and developer) friendly: + + 1. There's a new search box on the front page: `#374`_. + 2. The correspondents & tags pages now have a column showing the number of + relevant documents: `#375`_. + 3. The Dockerfile has been tweaked to build faster for those of us who are + doing active development on Paperless using the Docker environment: + `#376`_. + + 2.0.0 ===== @@ -430,6 +444,7 @@ bulk of the work on this big change. .. _Kyle Lucy: https://github.com/kmlucy .. _thinkjk: https://github.com/thinkjk .. _mcronce: https://github.com/mcronce +.. _Enno Lohmeier: https://github.com/elohmeier .. _#20: https://github.com/danielquinn/paperless/issues/20 .. _#44: https://github.com/danielquinn/paperless/issues/44 @@ -500,6 +515,9 @@ bulk of the work on this big change. .. _#351: https://github.com/danielquinn/paperless/pull/351 .. _#352: https://github.com/danielquinn/paperless/pull/352 .. _#354: https://github.com/danielquinn/paperless/issues/354 +.. _#374: https://github.com/danielquinn/paperless/pull/374 +.. _#375: https://github.com/danielquinn/paperless/pull/375 +.. _#376: https://github.com/danielquinn/paperless/pull/376 .. _pipenv: https://docs.pipenv.org/ .. _a new home on Docker Hub: https://hub.docker.com/r/danielquinn/paperless/ From e7daf7dae41c5919088cdbf826a347611b22a6d5 Mon Sep 17 00:00:00 2001 From: Daniel Quinn Date: Sun, 8 Jul 2018 16:06:57 +0100 Subject: [PATCH 08/11] Support css & js overrides --- .gitignore | 2 + docs/changelog.rst | 7 ++++ docs/customising.rst | 27 +++++++++++++ docs/index.rst | 1 + src/documents/templates/admin/base_site.html | 40 ++++++++++++++++++++ src/documents/templatetags/customisation.py | 37 ++++++++++++++++++ src/paperless/settings.py | 4 +- 7 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 docs/customising.rst create mode 100644 src/documents/templates/admin/base_site.html create mode 100644 src/documents/templatetags/customisation.py diff --git a/.gitignore b/.gitignore index 617cf507a..a16f958a3 100644 --- a/.gitignore +++ b/.gitignore @@ -61,6 +61,8 @@ target/ media/documents/*.gpg media/documents/thumbnails/* media/documents/originals/* +media/overrides.css +media/overrides.js # Sqlite database db.sqlite3 diff --git a/docs/changelog.rst b/docs/changelog.rst index f3442fe9a..84cc6bae9 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -14,6 +14,11 @@ Changelog doing active development on Paperless using the Docker environment: `#376`_. +* You now also have the ability to customise the interface to your heart's + content by creating a file called ``overrides.css`` and/or ``overrides.js`` + in the root of your media directory. Thanks to `Mark McFate`_ for this + idea: `#371`_ + 2.0.0 ===== @@ -445,6 +450,7 @@ bulk of the work on this big change. .. _thinkjk: https://github.com/thinkjk .. _mcronce: https://github.com/mcronce .. _Enno Lohmeier: https://github.com/elohmeier +.. _Mark McFate: https://github.com/SummittDweller .. _#20: https://github.com/danielquinn/paperless/issues/20 .. _#44: https://github.com/danielquinn/paperless/issues/44 @@ -515,6 +521,7 @@ bulk of the work on this big change. .. _#351: https://github.com/danielquinn/paperless/pull/351 .. _#352: https://github.com/danielquinn/paperless/pull/352 .. _#354: https://github.com/danielquinn/paperless/issues/354 +.. _#371: https://github.com/danielquinn/paperless/issues/371 .. _#374: https://github.com/danielquinn/paperless/pull/374 .. _#375: https://github.com/danielquinn/paperless/pull/375 .. _#376: https://github.com/danielquinn/paperless/pull/376 diff --git a/docs/customising.rst b/docs/customising.rst new file mode 100644 index 000000000..8110e214a --- /dev/null +++ b/docs/customising.rst @@ -0,0 +1,27 @@ +.. _customising: + +Customising Paperless +##################### + +Currently, the Paperless' interface is just the default Django admin, which +while powerful, is rather boring. If you'd like to give the site a bit of a +face-lift, or if you simply want to adjust the colours, contrast, or font size +to make things easier to read, you can do that by adding your own CSS or +Javascript quite easily. + + +.. _customising-overrides: + +Overrides +========= + +On every page load, Paperless looks for two files in your media root directory +(the directory defined by your ``PAPERLESS_MEDIADIR`` configuration variable or +the default, ``/media/``) for two files: + +* ``overrides.css`` +* ``overrides.js`` + +If it finds either or both of those files, they'll be loaded into the page: the +CSS in the ````, and the Javascript stuffed into the last line of the +````. diff --git a/docs/index.rst b/docs/index.rst index dbeade955..7710a330c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -40,6 +40,7 @@ Contents utilities guesswork migrating + customising extending troubleshooting scanners diff --git a/src/documents/templates/admin/base_site.html b/src/documents/templates/admin/base_site.html new file mode 100644 index 000000000..8d5e903d6 --- /dev/null +++ b/src/documents/templates/admin/base_site.html @@ -0,0 +1,40 @@ +{% extends 'admin/base_site.html' %} + +{# NOTE: This should probably be extending base.html. See CSS comment below details. #} + + +{% load custom_css from customisation %} +{% load custom_js from customisation %} + + +{% block blockbots %} + + {% comment %} + This really should be extending `extrastyle`, but the the + django-flat-responsive package decided that it wanted to put its CSS in + this block, so to make sure that overrides are in fact overriding + everything else, we have to do the Wrong Thing here. + + Once we switch to Django 2.x and drop django-flat-responsive, we should + switch this to `extrastyle` where it should be. + {% endcomment %} + + {{ block.super }} + + {% custom_css %} + +{% endblock blockbots %} + + +{% block footer %} + + {% comment %} + The Django admin doesn't have a block for Javascript you'd want placed in + the footer, so we have to use this one instead. + {% endcomment %} + + {{ block.super }} + + {% custom_js %} + +{% endblock footer %} diff --git a/src/documents/templatetags/customisation.py b/src/documents/templatetags/customisation.py new file mode 100644 index 000000000..793fd0eb3 --- /dev/null +++ b/src/documents/templatetags/customisation.py @@ -0,0 +1,37 @@ +import os + +from django import template +from django.conf import settings +from django.utils.safestring import mark_safe + +register = template.Library() + + +@register.simple_tag() +def custom_css(): + theme_path = os.path.join( + settings.MEDIA_ROOT, + "overrides.css" + ) + if os.path.exists(theme_path): + return mark_safe( + ''.format( + os.path.join(settings.MEDIA_URL, "overrides.css") + ) + ) + return "" + + +@register.simple_tag() +def custom_js(): + theme_path = os.path.join( + settings.MEDIA_ROOT, + "overrides.js" + ) + if os.path.exists(theme_path): + return mark_safe( + ''.format( + os.path.join(settings.MEDIA_URL, "overrides.js") + ) + ) + return "" diff --git a/src/paperless/settings.py b/src/paperless/settings.py index 6dd0b6419..91d2d2651 100644 --- a/src/paperless/settings.py +++ b/src/paperless/settings.py @@ -67,12 +67,12 @@ INSTALLED_APPS = [ "reminders.apps.RemindersConfig", "paperless_tesseract.apps.PaperlessTesseractConfig", - "flat_responsive", + "flat_responsive", # TODO: Remove as of Django 2.x "django.contrib.admin", "rest_framework", "crispy_forms", - "django_filters" + "django_filters", ] From 6c3afd21b948f8adfa8d1c72b9c2f0fb8c6a11b1 Mon Sep 17 00:00:00 2001 From: Daniel Quinn Date: Sun, 8 Jul 2018 16:07:10 +0100 Subject: [PATCH 09/11] Code cleanup --- src/documents/forms.py | 1 - src/paperless/middleware.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/documents/forms.py b/src/documents/forms.py index 5f965a1c6..3cdef448e 100644 --- a/src/documents/forms.py +++ b/src/documents/forms.py @@ -8,7 +8,6 @@ from django import forms from django.conf import settings from .models import Document, Correspondent -from .consumer import Consumer class UploadForm(forms.Form): diff --git a/src/paperless/middleware.py b/src/paperless/middleware.py index 8fed7da8f..58cdad65c 100644 --- a/src/paperless/middleware.py +++ b/src/paperless/middleware.py @@ -2,7 +2,7 @@ from django.utils.deprecation import MiddlewareMixin from .models import User -class Middleware (MiddlewareMixin): +class Middleware(MiddlewareMixin): """ This is a dummy authentication middleware class that creates what is roughly an Anonymous authenticated user so we can disable login From 3f4ac1f2f1ad0f92ad63383acdf50b4d4f4bc11e Mon Sep 17 00:00:00 2001 From: Daniel Quinn Date: Sun, 8 Jul 2018 16:07:19 +0100 Subject: [PATCH 10/11] Set the correct version number --- src/paperless/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/paperless/version.py b/src/paperless/version.py index 3be2947f7..fc2d6561c 100644 --- a/src/paperless/version.py +++ b/src/paperless/version.py @@ -1 +1 @@ -__version__ = (1, 3, 0) +__version__ = (2, 1, 0) From 088a631f6a24644957d323eaa148cc75f7de0048 Mon Sep 17 00:00:00 2001 From: Daniel Quinn Date: Sun, 8 Jul 2018 17:16:13 +0100 Subject: [PATCH 11/11] Add note for css/js overrides --- docs/customising.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/customising.rst b/docs/customising.rst index 8110e214a..0d8e428cd 100644 --- a/docs/customising.rst +++ b/docs/customising.rst @@ -25,3 +25,18 @@ the default, ``/media/``) for two files: If it finds either or both of those files, they'll be loaded into the page: the CSS in the ````, and the Javascript stuffed into the last line of the ````. + + +.. _customising-overrides-note: + +An important note about customisation +------------------------------------- + +Any changes you make to the site with your CSS or Javascript are likely to +depend on the structure of the current HTML and/or the existing CSS rules. For +the most part it's safe to assume that these bits won't change, but *sometimes +they do* as features are added or bugs are fixed. + +If you make a change that you think others would appreciate though, submit it +as a pull request and maybe we can find a way to work it into the project by +default! \ No newline at end of file