Есть у нас один сервер, на котором живет несколько простых сайтов. Код каждого сайта выполняется от своего пользователя (с помощью MPM ITK), лежит в домашнем каталоге пользователя, который пользователь естественным образом к коду и данным других сайтов доступа не имеет. Мы имеем типичный образец виртуального хостинга.

Теперь мы захотели чтобы статические файлы эффективно, как он это умеет, раздавал nginx, делая это прозрачно для всех пользователей при минимуме усилий и времени на поддержку со стороны администратора.

Но возникает проблема: как дать nginx доступ к чтению файлов пользователей, и при этом не дать пользователям читать файлы соседа?

Нет ничего проще!

Достаточно добавить пользователя, с которым работает nginx, а обычно это www-data, в группу пользователя, к файлам которого nginx должен иметь доступ:

useradd --create-home --user-group test.example.com
gpasswd -a www-data test.example.com

Здесь мы создали пользователя test.example.com, который входит один, и только один, в одноименную группу test.example.com. Затем мы добавили в эту группу пользователя www-data.

Теперь nginx сможем прочитать все, для чего есть доступ у группы того пользователя. При этом у пользователя test.example.com остается возможность закрыть доступ к чему-либо для nginx просто на всякий случай:

chmod go-rwx ~/.ssh/

Если идти дальше...

Можно найти в /usr/local/bin скрипт addwwwuser для добавления пользователей и раздачи прав в автоматическом режиме.

#!/bin/sh
set -o nounset -o errexit
USER="$1"
shift
useradd -m -U -G users -s /bin/bash "$@" "$USER"
gpasswd -a www-data "$USER"
echo "$USER:$(pwgen -s 20)" | chpasswd

Если хочется чего-то странного...

Всего того же самого можно добиться с помощью ACL.

  1. Нужно убедиться что целевая файловая система поддерживает установку ACL, и перемонтировать её, если нужно, с опцией acl:

    mount -o remount,acl /home
    
  2. Так как nginx должен получить необходимый минимум прав, то есть права только на чтение и вход в поддиректории, дадим ему право заходить в домашнюю директорию пользователя test.example.com и в подкаталог, где есть каталог, в котором есть статические файлы для раздачи:

    setfacl -m user:www-data:--x /home/test.example.com
    setfacl -m user:www-data:--x /home/test.example.com/www
    

    Файлы и каталоги внутри указанных директорий, доступ к которым явно не разрешен, nginx читать не сможет:

    /home/test.example.com$ ls .ssh
    ls: cannot open directory .ssh: Permission denied
    
  3. Теперь дадим nginx право читать те самые статические файлы, которые в нашем случае находятся в htdocs:

    setfacl -R -m d:u:www-data:rX /home/test.example.com/www/htdocs
    

Эти права будут рекурсивно (-R) распространены на все лежащее ниже в дереве файлов, и на все новые файлы. То есть, вся эта схема будет работать прозрачно для пользователя. Чего мы и добивались. Но стоило ли так заморачиваться?