Django [Errno 13] Разрешение отклонено: '/var/www/media/animals/user_uploads'
Я разрабатываю django API, который будет работать поверх Apache2 через WSGI на сервере под управлением Ubuntu.
Пользователи смогут загружать изображения, которые они берут на сервер, используя запрос POST. API обрабатывает этот запрос, а затем пытается записать изображение в /var/www/media/animals/user_uploads/<animal_type>/<picture_name>.jpg
. Если нет каталога /var/www/media/animals/user_uploads/<animal_type>/
, он создаст его.
При тестировании во время разработки все было в порядке, как с использованием Windows, так и с Scientific Linux. При тестировании на сервере развертывания я получаю эту ошибку:
![Django Error]()
Насколько я понимаю, сервер Apache2 работает с использованием пользователя www-data
. В моем случае, запустив cat /etc/passwd
, чтобы получить список пользователей, это то, что я получаю для www-data
:
WWW-данные: х: 33: 33: WWW-данные:/Var/WWW:/бен/ш
Я предполагаю, что это означает, что www-data
имеет доступ ко всему в /var/www/
. Я пробовал:
chmod 777 -R media
Это сработало, но, очевидно, это очень плохой способ решить эту проблему. Есть ли лучший способ решить эту проблему?
Это мой 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()
У меня есть это в моем файле settings.py
:
MEDIA_ROOT = '/var/www/media/'
MEDIA_URL = os.path.join(BASE_DIR,'/media/')
My vhost.conf
содержит следующее:
Alias /media/ /var/www/media/
Ответы
Ответ 1
Я решил это сам в конце.
При запуске на машинах разработки я фактически выполняю свои текущие пользовательские привилегии. Однако при запуске на сервере развертывания я фактически выполняю wsgi
, что означает, что он работает с привилегиями www-data
.
www-data
не является ни владельцем, ни группой пользователей, которые владеют /var/www
. Это означает, что www-data
рассматривается как other
и имеет права доступа к другим.
Решение BAD:
sudo chmod -R 777 /var/www/
Это даст всем полный доступ ко всему, что есть в /var/www/
, что является очень плохой идеей.
Еще одно решение BAD:
sudo chown -R www-data /var/www/
Это изменит владельца на www-data
, который откроет уязвимости безопасности.
Решение ХОРОШЕЕ:
sudo groupadd varwwwusers
sudo adduser www-data varwwwusers
sudo chgrp -R varwwwusers /var/www/
sudo chmod -R 760 /var/www/
Это добавляет www-data
в группу varwwwusers
, которая затем устанавливается как группа для /var/www/
и всех ее подпапок. chmod
предоставит владельцу права на чтение, запись и выполнение, но группа не сможет выполнить какой-либо script потенциально загруженный там, если, например, взломан веб-сервер.
Вы можете установить его на 740
, чтобы сделать его более безопасным, но тогда вы не сможете использовать функциональность Django's
collectstatic
, поэтому придерживайтесь 760
, если вы не уверены в том, что вы делает.
Ответ 2
У меня была похожая проблема в Django 1.10, и эта страница была первым результатом Google, но принятое решение не решило мою проблему.
С каталогом MEDIA, расположенным в корне моего проекта для хранения файлов, мне просто нужно было установить:
MEDIA_ROOT = os.path.join(BASE_DIR,'MEDIA')
а потом я перестал получать ошибку.
Ответ 3
Чтобы узнать, к какому пользователю вы вошли в систему:
$ whoami
ubuntu
И добавив в свое решение, если вы используете экземпляр AWS, вы должны добавить своего пользователя в группу, чтобы иметь доступ к этой папке:
Создание группы для пользователей веб-сервисов (varwwwersers)
$ sudo groupadd varwwwusers
Измените папку www и сделайте ее принадлежащей производителю
$ sudo chgrp -R varwwwusers /var/www/
www-data - сервер, создающий запросы django, добавляет его в группу
$ sudo adduser www-data varwwwusers
Изменить политику папки
$ sudo chmod -R 770 /var/www/
Добавьте ubuntu в группу произвольных пользователей
$ usermod -a -G varwwwusers ubuntu
Надеюсь, это поможет!
Ответ 4
Решение этой проблемы при работе с рабочим сервером будет заключаться в том, чтобы использовать collectstatic, как уже упоминалось, что он использовал и разрешал, или предоставлять разрешения для папок. Однако, если ваше решение находится в локальной среде, его можно получить, настроив локальный каталог MEDIA
в файле settings.py
, который действует на локальном сервере.
Итак, добавим эти две строки в локальный файл конфигурации, как упомянуто @Nic Scozzaro:
MEDIA_ROOT = os.path.join (BASE_DIR, 'media')
STATIC_ROOT = os.path.join (BASE_DIR, 'static')
После настройки перезапустите службы, чтобы применить исправления.