mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-11-03 19:17:13 -05:00 
			
		
		
		
	
							parent
							
								
									20a4a66a57
								
							
						
					
					
						commit
						6fd9995aa1
					
				
							
								
								
									
										141
									
								
								Pipfile.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										141
									
								
								Pipfile.lock
									
									
									
										generated
									
									
									
								
							@ -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",
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										435
									
								
								docs/setup.rst
									
									
									
									
									
								
							
							
						
						
									
										435
									
								
								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 <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 <IP>:<PORT>``.
 | 
			
		||||
   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 <paperless directory>/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;
 | 
			
		||||
 | 
			
		||||
        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 <path-to-paperless-static-directory>
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    server {
 | 
			
		||||
 | 
			
		||||
      listen 443 ssl;
 | 
			
		||||
      listen [::]:443;
 | 
			
		||||
      client_max_body_size 4G;
 | 
			
		||||
      server_name example.com;
 | 
			
		||||
      keepalive_timeout 5;
 | 
			
		||||
      root /var/www/example.com;
 | 
			
		||||
 | 
			
		||||
      ssl on;
 | 
			
		||||
 | 
			
		||||
      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;
 | 
			
		||||
 | 
			
		||||
      # 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;
 | 
			
		||||
 | 
			
		||||
      add_header Strict-Transport-Security max-age=15768000;
 | 
			
		||||
 | 
			
		||||
      ssl_stapling on;
 | 
			
		||||
      ssl_stapling_verify on;
 | 
			
		||||
 | 
			
		||||
      access_log /var/log/nginx/example.com.log main;
 | 
			
		||||
      error_log /var/log/nginx/example.com.err info;
 | 
			
		||||
 | 
			
		||||
        location / {
 | 
			
		||||
        try_files $uri @proxy_to_app;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      location @proxy_to_app {
 | 
			
		||||
            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 https;
 | 
			
		||||
        proxy_set_header Host $host;
 | 
			
		||||
        proxy_redirect off;
 | 
			
		||||
        proxy_pass http://transfer_server;
 | 
			
		||||
            proxy_set_header X-Forwarded-Proto $scheme;
 | 
			
		||||
 | 
			
		||||
            proxy_pass http://127.0.0.1:8000
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
Once you've got Nginx configured, you'll want to have a configuration file for
 | 
			
		||||
your gunicorn instance.  This should do the trick:
 | 
			
		||||
The gunicorn server can be started with the command:
 | 
			
		||||
 | 
			
		||||
.. code:: python
 | 
			
		||||
.. code-block:: shell
 | 
			
		||||
 | 
			
		||||
    import os
 | 
			
		||||
    $ <path-to-paperless-virtual-environment>/bin/gunicorn <path-to-paperless>/src/paperless.wsgi -w 2
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
    def post_fork(server, worker):
 | 
			
		||||
        server.log.info("Worker spawned (pid: %s)", worker.pid)
 | 
			
		||||
.. _setup-subdirectory:
 | 
			
		||||
 | 
			
		||||
    def pre_fork(server, worker):
 | 
			
		||||
        pass
 | 
			
		||||
Consumer
 | 
			
		||||
++++++++
 | 
			
		||||
 | 
			
		||||
    def pre_exec(server):
 | 
			
		||||
        server.log.info("Forked child, re-executing.")
 | 
			
		||||
Once you've tested things and are happy with the work flow, you can automate
 | 
			
		||||
the process of starting the webserver and consumer automatically.
 | 
			
		||||
 | 
			
		||||
    def when_ready(server):
 | 
			
		||||
        server.log.info("Server is ready. Spawning workers")
 | 
			
		||||
.. _setup-permanent-standard-systemd:
 | 
			
		||||
 | 
			
		||||
    def worker_int(worker):
 | 
			
		||||
        worker.log.info("worker received INT or QUIT signal")
 | 
			
		||||
Standard (Bare Metal + Systemd)
 | 
			
		||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
        ## 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))
 | 
			
		||||
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.
 | 
			
		||||
 | 
			
		||||
    def worker_abort(worker):
 | 
			
		||||
        worker.log.info("worker received SIGABRT signal")
 | 
			
		||||
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``.
 | 
			
		||||
 | 
			
		||||
.. code-block:: bash
 | 
			
		||||
 | 
			
		||||
    $ 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
 | 
			
		||||
 | 
			
		||||
.. code-block:: bash
 | 
			
		||||
 | 
			
		||||
    $ systemctl enable paperless-consumer
 | 
			
		||||
    $ systemctl enable paperless-webserver
 | 
			
		||||
    $ systemctl start paperless-consumer
 | 
			
		||||
    $ systemctl start paperless-webserver
 | 
			
		||||
 | 
			
		||||
.. _setup-permanent-vagrant:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Standard (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 <path to paperless virtual environment>/bin/gunicorn <path to parperless>/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 <path to paperless virtual environment>/bin/python <path to parperless>/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
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user