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
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:
Nginx config:
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.If the application is so simple that a simple "/prefix" can be added to one line in
urls.py
then I prefer this simple solution without anything more.Otherwise the "/prefix" must be appended to the
domain
column in the record for your site in Sites table in Django admin. The domain should be then "example.com/project" with the second solution, because Django must know the domain and the prefix, especially for correct redirect. Naturally the prefix must be also stripped from URL of the request by webserver, as you do it now in nginx settings.I usually split the verification of such deployments to two questions:
I use both nginx log and Django logging enabled to see which of them is eventually miscofigured. (You didn't wrote enough important information.)
An important case that should be tested is: Verify that web pages that require athentication are redirected to login page correctly back and forth, even if you try these URLs after logout.
More details can be found in the similar question.
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:
Hosting multiple apps in the same process (aka managing SCRIPT_NAME and PATH_INFO)
mount
can take the place ofmodule
For Django specifically,
Eventually gave up on trying to do this "neatly".
The final solution was just to make a settings variable that I prefixed to the static_url and projects urls.py file. No SCRIPT_NAME or anything complicated on the nginx side.
First of all, remove
uwsgi_modifier1 30;
. Django will handleSCRIPT_NAME
by itself and don't need to havePATH_INFO
rewritten by uWSGI. It can be harmful ifSCRIPT_NAME
isn't removed from headers by uWSGI.Secondly, remove
uwsgi_param PATH_INFO "$1";
from nginx config.PATH_INFO
is already defined in uwsgi_params file, and it should be$document_uri
(as it is in uwsgi_params), not$1
if you're passingSCRIPT_NAME
to django.After that tweaks, django should treat
SCRIPT_NAME
as URL prefix and will adjust url dispatcher and url reversing to that.