Vlad Schnakovszki Vlad Schnakovszki - 4 months ago 17
Linux Question

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

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:

Django 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/

Answer

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 obviously 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. chmod will give read, write, execute permissions to the owner and the group, while blocking any other users from accessing it.