paperless icon indicating copy to clipboard operation
paperless copied to clipboard

Deploy at non root URL

Open viharm opened this issue 8 years ago • 14 comments

This seems like a very good application. Thank you for efforts in creating this app. I respect the vision and agree with it.

I am trying to deploy this behind in existing environment which has an Apache installation serving several websites.

I would like to use my Apache webserver as a reverse proxy to access paperless. However I am also deploying this at a non-root URL of an existing virtual host, e.g., https://mydomain.tld/paperless

When I setup the reverse proxy, the Django service keeps throwing back the root URL, thus failing. Is there a configuration for setting this path/URL?

Regards.

viharm avatar Aug 10 '17 15:08 viharm

I've never done something like that before, but a cursory search online pointed me to FORCE_SCRIPT_NAME which might be your best bet.

I suggest editing paperless/settings.py and adding FORCE_SCRIPT_NAME = "paperless" to the bottom and restarting the server to see if that works. If it does, issue a pull request that follows the other settings vars use of environment variables and I'll roll it into master.

If it doesn't work however, I'm afraid I don't know how to do that :-( I'm not opposed to making it work though, should someone else know how to do it.

danielquinn avatar Aug 14 '17 17:08 danielquinn

I only know how to do this for deployments using uWSGI. This is part of my nginx config for another project:

location /blog/ {
                uwsgi_pass      127.0.0.1:8780;
                include         uwsgi_params;
                uwsgi_param SCRIPT_NAME /blog;
                # tell uwsgi to remove SCRIPT_NAME from the URL
                uwsgi_modifier1 30;
        }

Googling for SCRIPT_NAME, it seems also possible to set this as environment variable for django in a wsgi file. But that setting sounds like it should do the job.

MasterofJOKers avatar Aug 14 '17 18:08 MasterofJOKers

I run my instance at /paperless/. I run in docker, so I just run this before it starts to modify the necessary hardcoded URLs:

sed -i 's=/fetch=/paperless/fetch=' /usr/src/paperless/src/documents/admin.py
sed -i -e 's=/admin/login=/paperless/admin/login=' -e 's=/static/=/paperless/static/=' -e 's=/media/=/paperless/media/=' /usr/src/paperless/src/paperless/settings.py
sed -i -e 's=r"^=r"^paperless/=' -e 's=r"admin=r"paperless/admin=' -e 's=r""=r"paperless"=' /usr/src/paperless/src/paperless/urls.py

It's not the cleanest way, but it does work.

kmlucy avatar Jan 14 '18 15:01 kmlucy

Hi guys, I finally got around to fixing this tonight -- I hope -- your own responses will help determine if that's true ;-) Just do a git pull to get the changes.

@kmlucy, thanks to your URL hack above, I was able to track down all of the hard-coded URLs and replace them with properly named ones. Hopefully that will clean things up for you. @ovv's advice in #323 about configuring Nginx however may still be necessary. YMMV.

Assuming this works out, would any of you care to write some documentation about how you've made Paperless work on a subfolder?

danielquinn avatar Apr 13 '18 19:04 danielquinn

I updated Paperless, removed my URL hack, and updated my NGINX config. Now I am getting a DisallowedRedirect error when I try to navigate to URL.com/paperless.

Environment:


Request Method: GET
Request URL: http://URL.com/paperless/

Django Version: 1.11.12
Python Version: 3.6.3
Installed Applications:
['django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django_extensions',
 'documents.apps.DocumentsConfig',
 'reminders.apps.RemindersConfig',
 'paperless_tesseract.apps.PaperlessTesseractConfig',
 'flat_responsive',
 'django.contrib.admin',
 'rest_framework',
 'crispy_forms',
 'django_filters']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'paperless.middleware.Middleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback:

File "/usr/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
  41.             response = get_response(request)

File "/usr/lib/python3.6/site-packages/django/core/handlers/base.py" in _legacy_get_response
  249.             response = self._get_response(request)

File "/usr/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  187.                 response = self.process_exception_by_middleware(e, request)

File "/usr/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/usr/lib/python3.6/site-packages/django/views/generic/base.py" in view
  68.             return self.dispatch(request, *args, **kwargs)

File "/usr/lib/python3.6/site-packages/django/views/generic/base.py" in dispatch
  88.         return handler(request, *args, **kwargs)

File "/usr/lib/python3.6/site-packages/django/views/generic/base.py" in get
  193.                 return http.HttpResponsePermanentRedirect(url)

File "/usr/lib/python3.6/site-packages/django/http/response.py" in __init__
  431.             raise DisallowedRedirect("Unsafe redirect to URL with protocol '%s'" % parsed.scheme)

Exception Type: DisallowedRedirect at /
Exception Value: Unsafe redirect to URL with protocol 'admin'

kmlucy avatar Apr 14 '18 15:04 kmlucy

@kmlucy yeah I screwed that one up -- I don't know how to make it work for people running paperless on a subdirectory, sorry.

I've reverted that one line to the hard-coded redirect to /admin/, so you'll need to apply that patch to run it until someone sends me a PR that will make it work.

danielquinn avatar Apr 16 '18 08:04 danielquinn

@danielquinn No worries. My way works for me just fine, it just isn't very portable. If somebody figures out a cleaner way to do it, that's great, but no rush from my end. I looked into it a little, but it's outside my abilities.

kmlucy avatar Apr 16 '18 10:04 kmlucy

I'm not using docker as in #353 but I am using gunicorn with a unix socket, with paperless-2.1.0

I was able to get this working up to a point. I have:

PAPERLESS_FORCE_SCRIPT_NAME=/papers
PAPERLESS_STATIC_URL="/papers/static/"

And my nginx proxy code is:

# paperless
location /papers {
    proxy_pass http://unix:/tank/srvdata/paperless/paperless.sock;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}
location /papers/static {
    autoindex on;
    alias /tank/srvdata/paperless/paperless-2.1.0/static;
}

This works for loading the site and signing in. However when I add my first document, it won't load thumbnails. I get 404 errors on https://example.com/papers/fetch/thumb/1

I tried setting PAPERLESS_MEDIA_URL="/papers/media/" in case that was needed but it didn't fix the issue; I'm not clear what that setting is for or how to use it.

I tried the PAPERLESS_MEDIA_URL along with adding the following to nginx:

location /papers/media {
    autoindex on;
    alias /tank/srvdata/paperless/media;
}

Still no luck, though that was just guesswork. Any ideas?

EDIT TO ADD: with the above configuration the django error on directly trying to access https://example.com/papers/papers/fetch/thumb/1 is:

Using the URLconf defined in paperless.urls, Django tried these URL patterns, in this order:

^api/auth/ ^api/ ^fetch/(?Pdoc|thumb)/(?P\d+)$ [name='fetch'] ^push$ [name='push'] admin/ ^$ ^papers/media/(?P.*)$

The current path, papers/fetch/thumb/1, didn't match any of these.

apiontek avatar Sep 02 '18 17:09 apiontek

I am trying to solve this, too.

Any news here?

massaquah avatar Sep 08 '18 16:09 massaquah

The blocker/solution appears to be #353, as it's most of the way there, but there's still a problem with the handling of static files. I'm afraid I have no idea how to solve it, but if someone can come up with a solution that I can reproduce, I'll gladly merge it.

danielquinn avatar Sep 09 '18 20:09 danielquinn

Just wanted to add that I got paperless working under a subdir (/paperless) with the following config. In my case, paperless is run by gunicorn bound to localhost with apache2 running on the same machine as a first reverse proxy and then nginx as the final reverse proxy on a different machine.

In /etc/paperless.conf

PAPERLESS_MEDIA_URL="/paperless/media/"
PAPERLESS_STATIC_URL="/paperless/static/"
PAPERLESS_FORCE_SCRIPT_NAME="/paperless"

In /etc/apache2/sites-enabled/paperless.conf

Listen 8080

<VirtualHost *:8080>
    ServerName nextcloud
    
    ErrorLog /var/log/apache2/paperless-error.log

    ProxyPreserveHost off 
    ProxyPass / http://localhost:8000/
    ProxyPassReverse / http://localhost:8000/

    <Proxy http://localhost:8000/>
        Require all granted
        Options none
    </Proxy>
</VirtualHost>

In nginx I have the following config:

location /paperless {
    proxy_pass http://10.1.10.24:8080/;
    proxy_set_header Host "my.domain.org";
    proxy_set_header Referer "https://my.domain.org";
}

This allows me to access paperless on https://my.domain.org/paperless with the interface working.

The first reverse proxy is probably not necessary but I wasn't able to configure gunicorn to listen on all interfaces so I just put apache2 in front of it.

envy avatar Nov 12 '19 19:11 envy

Anyone have a working solution without a double proxy?

chadberg avatar Feb 13 '20 21:02 chadberg

Re: "Without double proxy", the middle Apache is not necessary.

I got it to work with envy's variables in docker-compose.env:

PAPERLESS_MEDIA_URL=/paperless/media/
PAPERLESS_STATIC_URL=/paperless/static/
PAPERLESS_FORCE_SCRIPT_NAME=/paperless

And set up my nginx as:

location /paperless/ {
        proxy_set_header        Host $host;
        proxy_set_header        X-Real-IP $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header        X-Forwarded-Proto $scheme;

        proxy_pass          http://127.0.0.1:[xxxx]/;
        proxy_redirect      http://localhost:[xxxx]/ https://[myshinydomain]/paperless/;
        proxy_read_timeout  60;
}

As with all locations in nginx, please make sure your location directive ends with a slash. /paperless/ (good) vs. /paperless (bad). This is important, because nginx.

Replace [xxxx] with whichever port you have assigned to the paperless web container, and obviously [myshinydomain] with your shiny domain.

RoyWolfe avatar Oct 01 '20 17:10 RoyWolfe

@RoyWolfe, thanks for posting your settings here. I've got my install working with at /paperless with one exception. On the Change Document page, the document preview no longer works. The generated HTML does not appear to be adding the /paperless/ to the front of the object data path

<div class="side-preview">
  <h2>Preview</h2>
  <object data="/fetch/preview/336"></object>
</div>

Are you experiencing similar issues?

jacobschwan avatar Oct 28 '20 02:10 jacobschwan