Django File Upload with nginx / gunicorn - media permissions - python

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.

Related

Django hosted on Apache - Uploading a file going to wrong location

I have a simple website that allows the user to upload a file to my server. I want the file to be uploaded into my django project folder in a sub directory.
Everything is working fine but when I use the upload feature on my website I get a permissions denied on the folder /var/www BUT the thing is I changed the DocumentRoot to equal /mnt/public/apps - which is where I want my uploaded files to go (the upload creates a sub directory).
I have correct permissions in /mnt/public but I can't figure out how to point django or apache so that my upload goes to the /mnt/public/apps root instead of /var/www
Any help would be greatly appreciated!
As Alasdair said in the comments, which was a super quick reply (thanks!), the correct fix for my problem was to add the MEDIA_ROOT variable to my settings.py file.

Django admin backend 'Operational Error' attempt to write a readonly database

This question seems to have been asked many times but all the solutions I have checked haven't yet worked for me. I am running nginx on a Ubuntu 14.04 server with Django 1.6.1 installed. I am attempting to use the default django admin backend for a project (usually at localhost/admin/).
The issue I run into is OperationalError at /admin/ attempt to write a readonly database
(Update when I changed chmod permissions for the db.sqlite3 file the error now reads OperationalError at /admin/ unable to open database file but I have checked every option on the Django Newbie Mistakes website for the answer and no dice)
Some answers talked about the r+w+x permissions for the generated database file db.sqlite3 as far as I can tell even 777 on the db file doesn't do anything so I've kept it at 656.
As far as I can tell the django project works find (all pages render fine, the /admin page renders without css. When i attempt to login using localhost/admin/ and click submit I get the django debug page with the error). They are all owned by root:root. I have tried changing permissions for every file and directory to be owned by www-data:www-data but nothing.
I have even tried changing the settings.py to have an absolute path to the db instead of os.path.join(BASE_DIR, 'db.sqlite3')
I think its down to an ownership problem but I'll take any help.
After all that hassle and 2+ hours of banging my head against a wall, the answer for the archives...
I was using gunicorn, I took a cookie cutter set up from Digital Ocean which made the user django. I thought it the cookie cutter approach would be a shortcut which was easy to modify and skipped the boring bits. It turns out in /etc/init/gunicorn.conf setuid and setgid was set to the user django. My fault for not reading the documentation and assuming these meant little.
If you are having this problem either delete setuid or setgid or set them to www-data.
This error usually caused by running the server as a different user (i guess you are running a linux machine). If you have created the project as a root/administrator and running the server as a user with lower status, then you will get the error.
try running the server with sudo permission, i.e
sudo python3 manage.py runserver

Security optimal file permissions django+apache+mod_wsgi

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.

secure django file permissions

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.

django gunicorn and nginx proxy giving 504 error

I went through all the related questions and could not find the answer, i went through the docs as well and tried all that i could, its my first time, hence having a hard time.
I have a simple django polls app with proper settings and static files, working locally.
As mentioned in the title i am trying to use django on a newly bought VPS, with nginx and gunicorn, i am using virtualenv as well.
Here is my folder structure on the server:
logs pid projhome scripts
inside the projhome i have the following directories:
bin djangopolls include lib local
as already mentioned parallel to the projhome folder i have scripts folder, with the following content:
source /home/django/projhq/bin/activate
kill `cat /home/username/pid/gunicorn.pid`
gunicorn_django -c /home/username/projhome/djangopolls/gunicorn_cfg.py
Now to start the server i need to go to the scripts folder and run the start script, i do that without any error, but when i check the IP i get 504 error.
Where am i wrong???
you might first want to cd into the directory where settings.py file is placed and then run gunicorn, so you can update your script.sh to first cd into the django project directory.

Categories

Resources