Django [Errno 13] Permission denied: '/var/www/media/animals/user_uploads'

apache, django, linux, python, ubuntu

Solution

I have solved this myself in the end.

When running on the development machines, I am in fact running using my current user's privileges. However, when running on the deployment server, I am in fact running through `wsgi`, which means it's running using `www-data`'s privileges.

`www-data` is neither the owner nor in the group of users that own `/var/www`. This means that `www-data` is treated as `other` and has the permissions set to others.

The BAD solution to this would be to do:

sudo chmod -R 777 /var/www/

This would give everyone full access to everything in `/var/www/`, which is a very bad idea.

Another BAD solution would be to do:

sudo chown -R www-data /var/www/

This would change the owner to `www-data`, which opens security vulnerabilities.

The GOOD solution would be:

sudo groupadd varwwwusers
sudo adduser www-data varwwwusers
sudo chgrp -R varwwwusers /var/www/
sudo chmod -R 770 /var/www/

This adds `www-data` to the `varwwwusers` group, which is then set as the group for `/var/www/` and all of its subfolders. You could set it to `750` to make it more secure but then you won't be able to use `Django's` `collectstatic` functionality so stick to `770` unless you're very confident about what you're doing.

Problem

I am developing a django API which will be running on top of Apache2 via WSGI on a server running Ubuntu. Users will be able to upload pictures they take to the server using a POST request. The API processes this request and then attempts to write the image to `/var/www/media/animals/user_uploads/<animal_type>/<picture_name>.jpg`. In case there is no directory `/var/www/media/animals/user_uploads/<animal_type>/` it will create it. When testing during development everything was fine, both using Windows and Scientific Linux. When testing on the deployment server, I receive this error: From what I understand, the Apache2 server is running using the user `www-data`. In my case, running `cat /etc/passwd` to get the list of users, this is what I get for `www-data`: www-data:x:33:33:www-data:/var/www:/bin/sh I am assuming this means that `www-data` has access to everything in `/var/www/`. I have tried: chmod 777 -R media This worked but it is obviously a very bad way to solve this. Is there a better way to solve this? This is my wsgi.py: ``` import os, sys os.environ.setdefault("DJANGO_SETTINGS_MODULE", "serengeti.settings") sys.path.append('/serengeti/django/serengeti') sys.path.append('/serengeti/django') from django.core.wsgi import get_wsgi_application application = get_wsgi_application() ``` I have this in my `settings.py` file: ``` MEDIA_ROOT = '/var/www/media/' MEDIA_URL = os.path.join(BASE_DIR,'/media/') ``` My `vhost.conf` contains this: ``` Alias /media/ /var/www/media/ ```

Original source

Related problems