I'm building a Django app that will need SSL on all user-facing pages. On other projects where SSL was required I've run into complications when serving media files from a different virtual host on the same server. For instance the page is: https://www.mysite.com but it's referencing http://media.mysite.com/css/screen.css, and the browser subsequently displays security warnings to the user.
My understanding is that it's Django best practice to keep static files on at least their own virtual host, which -- as far as I know -- requires a subdomain like media.blahblah.com.
Obviously there's plenty of Django apps on SSL, so I must be missing something. Any advice on how this is managed?
The general answer is that you'll need to change the URL you're using to reference your static files to one that uses HTTPS. Using a relative path (/static/css/screen.css) instead of an absolute URL (http://...) makes your media automatically switch from HTTP to HTTPS depending on the referring page, but does force your hand when trying to serve according to best practices described below.
If you're using Django 1.3 with contrib.staticfiles, it would appear that you would just need to change the STATIC_URL setting. If not, you'll have to update the paths manually (or however you are specifying your static assets).
Best practices for static media like CSS and JavaScript do dictate that you should serve them from a webserver (not just virtualhost) different from the one serving up your Django pages. The thought there is that you can use a low-footprint webserver to serve those simple files very quickly. If you serve them from the same webserver that is running your Django site, then most likely a number of extra modules are being loaded but not used for the requests where you're just serving a static file.
Since you need to serve secured static files, you have a couple of options:
You'll either need to get a separate (or wildcard) SSL certificate for your static files webserver.
Con: extra cost for the certificate
Con: you'll have to specify a different domain (instead of the relative paths described in the first paragraph) to serve your static files from.
Setup SSL on a reverse proxy that handles all of the requests for your site. You're still serving your static files and Django pages from separate webservers, but the proxy knows which one to connect to based on the URL or path (ex: proxy "/static" from the static webserver, all else from the Django webserver).
Pro: Does allow you to use relative paths to your media.
Con: Extra systems configuration.
Related
I don't know if I missed information regarding this. But I want to know how to store static files to a different VM. I've read that some recommend doing that to larger sites to seperate the load.
My current setup is that I use one computer engine with nginx, virtualenv, gunicorn etc. I use nginx to display the static files (including the media files) on the same server.
How can I push media files to a seperate nginx server when a user uploads an image? How can I obtain the same url as well?
Let's first explore the options of static resources(Javascript, CSS, Images, Fonts etc...)
You have complete control of where this static content should go during the deployment. Typically these resources will go for compression during the build process to optimize the content size to reduce the bandwidth.
Deploy the static resource on the different server(VM with ngnix) and configure that URL in the Django settings.py with STATIC_URL. If you use the cookieless domain, it will save little more bandwidth. Refer the section Use Cookie-free Domains for Components in this URL: https://developer.yahoo.com/performance/rules.html
You can use the content expiry settings for these resources to cache on the client for the specified duration.
Some best practices are mentioned in the official documentation: https://docs.djangoproject.com/en/1.10/howto/static-files/
For the media resources, you can save the files on the shared volume and run it on the different server same as static resources. You can configure that server URL in the Django settings.py with MEDIA_URL.
I know that it's not a good way to serve directly file and picture from django via views and urls dispatch, but if these files and pictures are served via the server (Apache), the whole world can see them. What if some files and pictures are private for the user, and only the connected user can see these files or pictures? In this case, I need to serve by django itself?
To serve private documents, you should use a Python view that does the security checks.
Here is an example.
If you are using Apache with mod_wsgi then you can use mod_xsendfile
You are essentially looking to run the authorisation for some resources via Django, pass a header back to Apache saying 'Hey dude, lighten up. This user is okay to access this' Apache will then handle returning the resource.
Rough steps (as in, rough enough that you will need to do a little more research using the links I provide as a starting point)
Apache needs to know which resources are public and which aren't. Create a sub directory under media for both of these types (Why not go crazxy and call them /media/public/ and /media/private/)
Set up an alias for the public directory and a WSGIScriptAlias for the protected dir, the protected alias will be pointing to your main site handler (probably django.wsgi)
Add settings to vhost:
XSendFile On
XSendFileAllowAbove On
Add an urlconf to your Django app that handles /media/protected/{whatever} and routes it through your auth Django app auth logic. An example of this is here
A useful snippet for the above is here
and another example for good measure here
I have an existing site with a number of documents being served staticly. Client wants to add login protection to the site - not a problem using django_auth. However, the files being served from apache are still downloadable?
Is there a way to restrict access?
Ideally, this would require the path to these docs not changing on the site.
Was thinking of removing the alias from the apache config and having that route to a view that has the #login_required decorator on it, and then forwarding on.
See Having Django serve downloadable files on how to set up Django to work with Apache X-Sendfile. You can wrap the X-Sendfile header sending with some authentication checks and you should be good to go.
I'm hosting a site on WebFaction using Django/mod_python/Python2.5. I've recently run into the concept of static files (when setting up my Django admin).
From what I understand, serving static files is simply the idea of telling the server to serve files directly from a specific directory, rather than first routing the request through apache, then mod_python, then django, and finally back to the user. In the case of WebFaction this helps especially since there are two Apache servers that your request must go through (your app's server and the main public server).
Why is it that when I setup Django's static files, it only needs the /media folder in /contrib/admin? Is it just that all of Django's static content is related to the admin panel?
When I want to serve my own static content (images, css, etc.) should I include it in the same /media folder or set up another alias for my own content (/my_media)?
Yes, the static files used by Django are pretty much related to images, javascript and css for the admin. All other static content comes from your application. You can keep both sets (yours and the admin) under the same server. Just set the appropriate folders in the settings file.
http://docs.djangoproject.com/en/dev/ref/settings/#admin-media-prefix
http://docs.djangoproject.com/en/dev/ref/settings/#media-root
http://docs.djangoproject.com/en/dev/ref/settings/#media-url
See this post for a little more information:
Django and Static Files
Django's static files (e.g. js, css, images, etc.) are all in the media folder, and are related to the admin panel.
On WebFaction to save processing power, and more importantly memory, it is better to serve these from your secondary apache server (or even better from nginx or lighttpd) without having to go through mod_python and Django.
I use the following folder setup for my files:
media
css
js
img
etc
admin
css
js
img
See http://forum.webfaction.com/viewtopic.php?id=1981 for how to setup nginx as your secondary server on WebFaction if you are interested.
Let's say you've setup your site using Pylons, Django and most of the site runs fine and according to the framework used. However, what if you had a custom section that was entirely say, composed of flat html files and its own set of images, which you didn't have time to actually incorporate using the framework and were forced to basically support, under the same domain? Should there be some sort of default controller/view that's super bare minimalistic or do frameworks such as these somehow offer support in some smart way?
I realize also that potentially one could setup a new subdomain and reroute it to an entirely different directory, but I'm just curious as to how one would solve this when forced to deal with a framework.
When serving static pages I'd rather avoid having Django or Pylons handle the request, and handle it with the web server only. Using Nginx, you'd use a directive like:
location / {
root /whatever/the/path/is/;
# if the file exists, return it immediately
if (-f $request_filename) {
break;
}
# pass requests to MVC framework
# i.e. proxy to another server on localhost:
proxy_pass http://127.0.0.1:80;
}
For pylons you should be able to drop your static html files in the public directory. If there isn't a controller for a url then I think pylons looks in the public folder next.
For Django, I would serve these in exactly the same way as you serve your static assets - in your site_media directory, along with subdirs for js, css and img, you could have an html directory. Then the URL would just be /site_media/html/whatever.html.
In Django take a look at flatpages. It's part of the django.contrib package and uses flatpages middleware to serve up flat HTML controlled through the admin interface. For basic purposes, serving up additional about pages or the like this should do the trick.
You could also just create an HTML folder and - using mod_python, at least - set no handler for that path in the Apache configuration file (e.g. vhost.conf).