I am looking for a baseline set of file permissions to keep a django installation as secure as possible.
I cannot seem to find any obvious reference either on the Django site or Google.
Any links or clues?
I use Apache + mod_wsgi + django. I have no upload directories to permission. This is a really basic setup.
I am currently running my code successfully thus:
/var/www/djangodir
/django
/3rdpartyapp
/myapp
/serverfiles/my.wsgi
all directorys: 755 owned by root.root
all files: 644 owned by root.root
exceptions to all files
-----------------------
settings.py file: 400 owned by apache.apache
my.wsgi: 400 owned by apache.apache
I dont like the 644 on all files and would like to tighten that up but can't seem to get away with 400 or 500. The wsgi app cannot import anything from django if I do.
Help!
Use mod_wsgi daemon mode and have your Django application run in it. Set user/group for that daemon process group to be a special dedicated Django application user different to the Apache user. Have the WSGI script file you use be outside of the Django project area.
The directory containing the WSGI script file then can be 700 if owned by the Apache user. The WSGI script file inside it need only be 400 and need not even be owned by the Apache user but could be owned by root or the dedicated Django application user. All the Apache user will need is the ability to see the WSGI script file in the directory, it will not need the ability to open the WSGI script file.
All your project code and virtual environment can then be in a directory structure owned by the dedicated Django user with all directories being 0700 and files readable/writeable as you see fit or as needed. Only the dedicated Django application user need have access because all accesses will be from the daemon process group running as that user.
By doing it this way you have restricted access so that the Apache user cannot even see your project code. That way if hosting other stuff on the same Apache, such as PHP, there is no risk that a break in to the PHP code can access the files.
Thanks for a great reply! I don't know how you find the time to answer all the questions I've seen your fingerprints on all these years, but you are doing a huge service to the entire python/django/wsgi community. I liked your blog entry: http://blog.dscpl.com.au 12/5/2012 about the dilution of good advice and goodwill on these forums. It is definitely a challenge googling past all the nonsense out there.
Anyway, for anybody watching this thread, this works.
root.root: 755 /var/saas <- topdir
apache.apache: 755 /var/saas/wsgi <- apache folder
vsn.vsn: 400 /var/saas/wsgi/vsn.wsgi <- wsgi file
vsn.vsn: 700 /var/saas/vsn <- django code
root.root: 700 /var/saas/scripts <- operations scripts
root.root: 700 /var/saas/config <- temp config folder
apache.apache 444 /var/www/html/static <- destination of django's: python ./manage.py collectstatic
I couldn't get this to work with apache permissions 700, but I am happy with 755. One of the great unsolved mysteries of apache I'm guessing.
Related
I have a question. I work with one guy who is developing in Php, I am developing in Django right know. This is my first time doing something for other people and he firstly asked me to put my application to Apache Web server document root(I think he didn't know that much about Django, and he did everything this way), so I did it, because I didn't know that much about Apache and servers. But right know I am scared because I have all the python files in document root and I realized that this Web server document root \www\myproject might be accessible to other people. How should I change it, where should I put it, what is the best practice? I am deploying with mod_wsgi and Apache 2.4. In the documentation it says, that I shouldn't put code in Web server document root too, but if I put it somewhere else can I access it the same way, like I used to when it was on the Web server document root? Will I have to do something other than changing paths in Apache config?
You should put the Django project anywhere on the machine except for the apache document root, for security reasons as you have pointed out.
You can then configure apache to pint to the location of your wsgi.py which can live in the Django project if you wish:
WSGIScriptAlias / <path to the wsgi.py>
I'm not aware of a standard place to put the Django project root directory, I guess it depends on the OS and the distribution.
I am working on a Django based application whose location on my disk is home/user/Documents/project/application. Now this application takes in some values from the user and writes them into a file located in a folder which is under the project directory i.e home/user/Documents/project/folder/file. While running the development server using the command python manage.py runserver everything worked fine, however after deployment the application/views.py which accesses the file via open('folder/path','w') is not able to access it anymore, because by default it looks in var/www folder when deployed via apache2 server using mod_wsgi.
Now, I am not putting the folder into /var/www because it is not a good practise to put any python code there as it might become readable clients which is a major security threat. Please let me know, how can I point the deployed application to read and write to correct file.
The real solution is to install your data files in /srv/data/myapp or some such so that you can give the webserver user correct permissions to only those directories. Whether you choose to put your code in /var/www or not, is a separate question, but I would suggest putting at least your wsgi file there (and, of course, specifying your <DocumentRoot..> correctly.
I'm trying to allow users of my django site to upload a file (mostly PDFs) to my server through a FileField on a model. However, I keep running into 'Errno 13 Permission Denied' when trying to use the upload field generated by my modelform.
I have found many potential solutions while searching around, but haven't been able to get anything to work properly so far. This is my first real deployment and I have probably confused myself. For reference, I am on Ubuntu 14.04, Django 1.6, & gunicorn+nginx.
Right now, my media root lies within my project directory at:
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
MEDIA_ROOT = os.path.join(BASE_DIR, "media/uploads")
The error indicates an issue with the proper directory, so it's going to the right spot.
I have tried to chown -r the media directory to www-data:www-data with no success. I poked around, figured out what user was running the python process and tried to set 'him' as the owner - didn't work. I flipped it back to its original owner and group (root:root) and tried to chmod -r to 755 and 770, both of which also failed to resolve the issue.
If I chmod -r to 777, then everything "works" - but that's not something I want to keep exposed for obvious reasons.
My static files are collecting and being served properly from a directory outside of my project root (/var/www/mysite/static), so I tried moving the media folder over there and repeating all of the above steps - same result.
How can I get my media folder to securely accept uploads and downloads from my users without leaving this security hole wide open?
Thank you!
First of all, media files folder has to be in you project's path, otherwise you'll be getting SuspiciousOpertion exception from Django, so don't put it in /var/www.
Also, the fact that you are using nginx, is not that relevant, important part is which user is nginx/django project is running under, whichever user it is (normally www-data, at least with apache+mod_wsgi), that user should be the owner of the media folder.
Once you change the owner to the right user (I assume www-data): sudo chown -R www-data:www-data .../media, make sure permissions are correct: sudo chmod -R u+rwX .../media.
Hope it helped. Let me know if it didn't. :)
Try upping the max_body_size in your nginx conf file:
server {
...
client_max_body_size 250M;
...
}
By default it's set to 1M which is possibly too small depending on what you're uploading.
I'm just about getting started on deploying my first live Django website, and I'm wondering how to set the Ubuntu server file permissions in the optimal way for security, whilst still granting the permissions required.
Firstly a question of directories: I'm currently storing the site in ~/www/mysite.com/{Django apps}, but have often seen people using /var/www/... or /srv/www; is there any reason picking one of these directories is better than the other? or any reason why keeping the site in my home dir is a bad idea?
Secondly, the permissions of the dir and files themselves. I'm serving using apache with mod_wsgi, and have the file WSGIScriptAlias / ~/www/mysite.com/mainapp/wsgi.py file. Apache runs as www-data user. For optimal security who should own the wsgi.py file, and what permissions should I grant it and its containing dir?
Similarly, for the www, www/mysite.com, and www/mysite.com/someapp directories? What are the minimal permissions that are needed for the dirs and files?
Currently I am using 755 and 644 for dir and files respecitvely, which works well enough which allows the site to function, but I wonder if it is optimal/too liberal. My Ubuntu user is the owner of most files, and www-data owns the sqlite dbs.
In regards to serving the application from your home directory, this is primarily preference based. However, deployment decisions may be made depending on the situation. For example, if you have multiple users making use of this server to host their website, then you would likely have the files served from their home directories. From a system administrator's perspective that is deploying the applications; you may want them all accessible from /var/www... so they are easier to locate.
The permissions you set for serving the files seem fine, however they may need to run as different users... depending on the number of people using this machine. For example, lets say you have one other application running on the server and that both applications run as www-data. If the www-data user has read permissions of Django's config file, then the other user could deploy a script that can read your database credentials.
I'm writing a web application in Python (on Apache server on a Linux system) that needs to connect to a Postgres database. It therefore needs a valid password for the database server. It seems rather unsatisfactory to hard code the password in my Python files.
I did wonder about using a .pgpass file, but it would need to belong to the www-data user, right? By default, there is no /home/www-data directory, which is where I would have expected to store the .pgpass file. Can I just create such a directory and store the .pgpass file there? And if not, then what is the "correct" way to enable my Python scripts to connect to the database?
No matter what approach you use, other apps running as www-data will be able to read your password and log in as you to the database. Using peer auth won't help you out, it'll still trust all apps running under www-data.
If you want your application to be able to isolate its data from other databases you'll need to run it as a separate user ID. The main approaches with this are:
Use the apache suexec module to run scripts as a separate user;
Use fast-cgi (fcgi) or scgi to run the cgi as a different user; or
Have the app run its own minimal HTTP server and have Apache reverse proxy for it
Of these, by far the best option is usually to use scgi/fcgi. It lets you easily run your app as a different unix user but avoids the complexity and overhead of reverse proxying.
Install the application and its config files in its own directory different from the static files directory and only readable by the application user.
Set another user to run the application and use the WSGIDaemonProcess directive.
All of that and much more is clearly described in the mod_wsgi site, in the Quick Configuration Guide, Configuration Guidelines and Configuration Directives