Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

nginx serving Django in a subdirectory through uWSGI

I have already gone through some previous threads: How do I set subdirectory in nginx with Django how to deploy django under a suburl behind nginx Serving flask app on subdirectory nginx + uwsgi

The basic lesson is that you should only need to configure your site(s-available) to achieve this. I have now tried various permutations of

server {
    listen 80;
    server_name www.example.com;

    location = /favicon.ico { 
        access_log off; 
        log_not_found off; 
    }

    location /static/ {
        root /path/to/project;
    }

    location /project/ {
        root            /path/to/project;
        include         /etc/nginx/uwsgi_params;
        uwsgi_param     SCRIPT_NAME /project;
        uwsgi_modifier1 30;
        uwsgi_param PATH_INFO "$1";
        uwsgi_pass      unix:/tmp/project.sock;
    }
}

Everything runs perfectly when I define location to be "/" (and remove SCRIPT_NAME, modifier1, PATH_INFO and root doesn't matter. But trying to use a subdirectory always results in Page not found (404):

Request URL:    http://www.example.com/project/project

(edit) It's ADDING a directory to the request. What am I not figuring out?

(tried forced_script_name - should't have to use this and gives other types of headaches - and uwsgi config setting)

EDIT:

location /project/ {
    root            /path/to/project;
    include         /etc/nginx/uwsgi_params;
    uwsgi_param     SCRIPT_NAME /project;
    uwsgi_pass      unix:/tmp/project.sock;
}

Does not work ... The socket is there and works when I configure for / - I just can't see what I'm missing.

UPDATE:

location ~ /project(?<path_info>/.*|$) {
    include         /etc/nginx/uwsgi_params;
    uwsgi_pass      unix:/tmp/project.sock;
    uwsgi_param     PATH_INFO $path_info;
    uwsgi_param     SCRIPT_NAME /project;
}

This loads up the site but all links point to http://example.com/link/to/something instead of http://example.com/project/link/to/something

like image 249
Bjorn Avatar asked Mar 04 '16 09:03

Bjorn


2 Answers

Cleanest Method for Latest Nginx/uWSGI Versions

Since uwsgi_modifier1 30 is removed in the latest versions and I felt like the mount-point stuff was too hacky, I had to use a newer method to serve Django in a subdirectory:

uWSGI config:

[uwsgi]
socket =        /tmp/project.sock

# Requires PCRE support compiled into uWSGI
route-run =     fixpathinfo:

Nginx config:

location /project {
    include         /etc/nginx/uwsgi_params;
    uwsgi_pass      unix:/tmp/project.sock;
    uwsgi_param     SCRIPT_NAME /project; # Pass the URL prefix to uWSGI so the "fixpathinfo:" route-rule can strip it out
}

NOTE: fixpathinfo: requires PCRE support to be compiled into uWSGI.

So if things aren't working, try installing libpcre and libpcre-dev, then recompile uwsgi with pip install -I --no-cache-dir uwsgi. uWSGI's internal routing subsystem requires the PCRE library to be installed before uWSGI is compiled/installed. More information on uWSGI and PCRE.

like image 195
Shane Avatar answered Oct 19 '22 13:10

Shane


The nginx uwsgi_modifier1 is deprecated in uWSGI.

Your goal is to be able to host a wsgi app from anywhere without the app needing to be adjusted to account for where it's being served from.

The current method for doing this in uWSGI is to map mountpoints for each URI app combination like so:

[uwsgi]
socket = 127.0.0.1:3031
; mount apps
mount = /app1=app1.py
mount = /app2=app2.py
; rewrite SCRIPT_NAME and PATH_INFO accordingly
manage-script-name = true

Hosting multiple apps in the same process (aka managing SCRIPT_NAME and PATH_INFO)

mount can take the place of module

For Django specifically,

; Before
module = django_app.wsgi:application
; After
mount = /django_app=django_app.wsgi:application
manage-script-name = true
like image 41
shanemgrey Avatar answered Oct 19 '22 11:10

shanemgrey