Django to serve static files with exceptions - django

In my production environment I have Nginx serving static files for my Django application, but while developing I let Django so the work.
I need to have Nginx serving all static files but those in a certain subdirectory. So, Django side, I need to intercept that directory and treat it differently.
How can I make Django dev server intercept all the calls to /static/* but not those to /static/myspecialfiles/*´ and hence write a url route to handle the GET calls to said/static/myspecialfiles/*´?

You need to tackle this in two areas, Django and nginx.
For Django, since running a local setup (when DEBUG=True) already serves static content from STATIC_ROOT automatically, just add a URL conf for your special files:
# in urls.py
url(r'^/static/specialfiles/', SpecialView.as_view(), name='special'),
Then, in your nginx conf, make sure you ignore that path so it actually reaches Django:
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://localhost:8000;
}
location /static/specialfiles/ {
proxy_pass http://localhost:8000;
}
location /static/ {
alias /home/ubuntu/dev/example/static/;
}
}
Since the locations are parsed sequentially, your special files will hit the django block before the generic static block.
But really you'd be best to just move your special files somewhere else.

Related

Why is static content request going to uwsgi?

I'm setting up my Django project to work with uwsgi and nginx. For static content, I have the following in my nginx.conf:
location /static {
alias /Users/me/mystatic; # your Django project's static files - amend as required
}
I have set STATIC_ROOT to /Users/me/mystatic and called collectstatic to copy all the static files into that directory. In my uwsgi log, I see GET requests for the static content. Since nginx is supposed to serve the static content, why is the GET request sent to uwsgi?
Make sure that STATIC_URL is set as "/static/".
The nginx conf should look something like this:
server {
listen 80 ;
server_name XXXX;
client_max_body_size 4G;
location /static/ {
alias <path-to-collectstatic>
}
location / {
include uwsgi_params;
uwsgi_pass unix:/tmp/uwsgi_web.sock;
}
}
Notice the appending / in location block for static
Last thing, make sure that application server is running with DEBUG as False
The issue was that I had placed my own nginx.conf in /usr/local/etc/nginx/sites-enabled, not /usr/local/etc/nginx/servers. In /usr/local/etc/nginx/nginx.conf, include servers/*; is at the end. Therefore, UWSGI was still serving the static files. I followed the django-nginx-uwsgi tutorial, and I assumed I had to create a new sites-enabled directory. I am using OS X.
I see on Linux, though, /etc/nginx/nginx.conf has include include /etc/nginx/sites-enabled/*; at the end, so the steps in the tutorial are applicable on Linux.
The extra / at the end of /static doesn't make a difference, but it doesn't hurt to have it at the end of all paths.

Disable execution of static files as code, with Django, Gunicorn, Nginx

Django 1.8 docs state that "If you are serving your own static files, be sure that handlers like Apache’s mod_php, which would execute static files as code, are disabled." How do I disable any such handlers that may exist for Gunicorn + Nginx?
Nginx by default does not have any handlers doing that. If there are no handlers configured in your server section in nginx configuration, there is nothing to worry about. If it's clean nginx install, there is nothing to worry about.
Also examine your nginx config if there is only one way to run python code - via gunicorn and django's wsgi.py file.
Basically the django devs are warning you about a well known web vulnerability.
https://www.owasp.org/index.php/Unrestricted_File_Upload
As nginx can only serve static files it must use an app server for dynamic pages, a handler (php-fpm, gunicorn, uwsgi).
Could be the case that you are using an old nginx's PHP config (with php-fpm as a handler), and you added gunicorn for serving a django app, then a user could manage to upload a PHP file to django's media dir and later execute it through your legacy PHP handler.
This is a very odd case, there are no chances this could happen to a fresh site, you never add a PHP handler for a django app.
A PHP handler looks like this:
location ~ \.php$ {
expires off;
fastcgi_pass 127.0.0.1:9001;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_keep_conn on;
}

Lazily serving Django static content with NGINX

Let's say I've got Django code rooted in /var/my_app. I've got a MEDIA_ROOT configured at /var/my_app/files, and MEDIA_URL is /var/my_app/files at /files. Serving these files through UWSGI (or gunicorn, etc.) works fine.
Now I am trying to use the NGINX try_files directive to serve them without hitting UWSGI. Here's what I've got:
location /files/* {
try_files /var/my_app$uri $uri;
}
Wherein my understanding is that if I am attempting to access $hostname/files/photos/thumbs/file.jpg, the above location matches, $uri is /files/photos/thumbs/file.jpg, NGINX tests /var/my_app/files/photos/thumbs/file.jpg and should return the file if it exists.
Instead, when I access that URI, I see the request passed through to UWSGI in the UWSGI log, even though the file exists at /var/my_app/files/photos/thumbs/file.jpg. What am I doing wrong? I read the docs on try_files, but clearly I am misunderstanding something.
For reference, here is the Django location block:
location / {
include uwsgi_params;
uwsgi_param UWSGI_SETENV DATABASE_URL=[redacted]
uwsgi_pass 127.0.0.1:3034;
}
Added Context
This configuration is targeted at lazily serving Django-generated thumbnails (using easy-thumbnails) if they do not yet exist.

Nginx is not serving Django static files

I just configured my first django server for a very basic django-website. I'm using Django 1.4 and Nginx 1.0.14 with supervisor and gunicorn.
The problem is that Nginx is not serving the static files as suposed, but I don't know the why because is my first time using it.
This is the path where really lives my static files:
/home/cristian/envs/santalupe.com/santalupe/santalupe/static
And this is the setting I've in my nginx config file:
# Django admin media.
location /media/ {
autoindex on;
alias /home/cristian/envs/santalupe.com/lib/python2.7/site-packages/django/contrib/admin/static/;
}
# Site media
location /static/ {
autoindex on;
alias /home/cristian/envs/santalupe.com/santalupe/santalupe/static/;
}
Please let me know what I need to do in this case because I have not idea about the real problem.
You aren't serving the admin media from Nginx, just normal media. Try something like:
location /admin/media/ {
# this changes depending on your python version
root /home/cristian/envs/santalupe.com/lib/python2.7/site-packages/django/contrib;
}
Note how there's no trailing slash and the path ends at contrib. I'm using almost exactly this code successfully in production.
Maybe manage.py collectstatic on server help you?
Here is good description on right solution https://docs.djangoproject.com/en/dev/howto/static-files/#serving-static-files-in-production

Add expires header to django with nginx

I use django_compress to compress my static files. All static files are collected under /static/ url using collectstatic command. Now I want to add expires headers to this files. There is no problem to do this with apache, but when I add to my nginx.conf:
location /static/ {
root /home/user/proj/static;
expires 7d;
}
and restart the server then static files are not served. What should I change?
The location is under server context.
Refs http://wiki.nginx.org/HttpCoreModule#root, a request such as http://yourserver/static/foo will be directed to /home/user/proj/static/static/foo . Is the static/static right structure on you server?
Also run nginx -t to ensure there is no error in configuration, before reload nginx.