РазделОбщие папки
ДокументацияРуководство

Общие папки: доступ подрядчика к папке сайта

Типичная просьба: «дайте подрядчику (сервису обмена, бухгалтерии, агентству) доступ по SFTP в одну папку нашего сайта». Первое, что приходит в голову, — создать пользователя и указать ему домашний каталог внутри сайта. В MonoPanel так делать не нужно и не получится:

  • sshd делает chroot в домашний каталог SFTP-пользователя и требует, чтобы каталог принадлежал root и был закрыт от записи для группы и остальных. Каталог сайта принадлежит владельцу сайта, а если отдать его root, туда не сможет писать сам сайт.
  • Панель рассчитывает, что дом каждого аккаунта — /var/www/<login> с data/www, логами, tmp и ACL для веб-сервера. Чужой путь в home рано или поздно сломает mp site fix, бэкапы или переезд.
  • Один unix-пользователь на аккаунт и дом с правами 0710 — это и есть изоляция клиентов друг от друга.

Вместо этого панель выдаёт общую папку: гость остаётся обычным аккаунтом со своим домом, а нужная папка сайта монтируется внутрь его chroot. Гость видит после входа только эту папку (и свой пустой data), файлы читают и пишут обе стороны и веб-сервер, а сайту можно запретить выполнять PHP из этой папки.

1. Как это устроено

При mp user share add панель:

  1. создаёт папку в docroot сайта (если её нет) — владелец сайта, права 2770, setgid держит группу владельца на новых файлах;
  2. ставит на папку ACL: гостю и владельцу rwx, веб-группе r-x, с наследованием на всё, что появится внутри;
  3. делает root-овую точку монтирования в доме гостя (/var/www/<гость>/<имя>) — chroot остаётся root-овым, sshd доволен;
  4. пишет и включает mount-юнит systemd с bind-монтированием папки в эту точку — переживает перезагрузку;
  5. с --no-php добавляет в конфигурацию сайта location, который отвечает 403 на любой .php, .phtml и .phar из этой папки;
  6. с --entry вписывает в дропин sshd блок Match User <гость> Group monopanel-sftp с internal-sftp -d /<имя>: сессия SFTP начинается прямо в папке, а не в корне chroot. Блок действует только на аккаунты без shell.

Из bind-маунта не выйти: символьные ссылки наружу внутри chroot не резолвятся, ../ упирается в дом гостя. На EL метки SELinux сайта сохраняются, отдельно ничего настраивать не нужно.

2. Пошагово

Пример: сайт vstrade.kz аккаунта bitrix, подрядчику нужна папка kaspy для обмена файлами.

Шаг 1. Гость. Если аккаунта у подрядчика ещё нет — создайте его без shell, SFTP ему хватит:

mp user add userkaspy --generate        # пароль печатается один раз

Пароль — для входа по SFTP (и в панель, где гость увидит только свои папки).

Шаг 2. Папка. Выдайте папку сайта. Путь считается от docroot сайта; папка создастся, если её нет:

mp user share add userkaspy --site vstrade.kz --path kaspy --no-php --entry

Флаг --no-php стоит оставлять всегда, когда папка нужна для файлов, а не для кода: иначе подрядчик может положить в неё .php, и сайт выполнит его от имени аккаунта bitrix — со всеми правами сайта. --name задаёт имя папки в доме гостя, если оно должно отличаться от последнего сегмента пути.

Флаг --entry делает папку точкой входа: подрядчик после подключения оказывается сразу в kaspy, как если бы это и был его домашний каталог. Без флага сессия начинается в доме, где видны data и kaspy. Точку входа можно назначить и позже, а также снять:

mp user share entry userkaspy kaspy        # входить сразу в kaspy
mp user share entry userkaspy kaspy --off  # снова в дом

У аккаунта одна точка входа: назначение новой снимает прежнюю. Аккаунту с shell точка входа не назначается — он и так ходит куда хочет.

Шаг 3. Проверка.

mp user share list userkaspy

Столбец MOUNTED должен показывать да, PHP — запрещён, ENTRY — да. Подрядчик подключается по SFTP как userkaspy с паролем из шага 1 и сразу оказывается в папке kaspy — она и есть /var/www/bitrix/data/www/vstrade.kz/kaspy сайта. На уровень выше лежит его дом с пустым data, дальше пути нет.

То же самое в Web UI: «Пользователи» → кнопка «папки» у аккаунта → сайт, папка, галочки «без PHP» и «точка входа» → «Добавить». Кнопка «точка входа» в таблице назначает и снимает её у уже выданной папки.

Шаг 4. Когда доступ больше не нужен.

mp user share rm userkaspy kaspy

Маунт и юнит снимаются, ACL гостя убираются, запрет PHP уходит из конфигурации сайта, точка входа — из дропина sshd. Файлы остаются в папке сайта. Удаление аккаунта гостя (mp user rm) или сайта делает то же самое само.

3. Права на файлы

  • Всё, что создаёт гость, принадлежит гостю, всё, что создаёт сайт, — владельцу сайта; благодаря наследуемым ACL обе стороны читают файлы друг друга, а nginx отдаёт их посетителям.
  • Файл, загруженный по SFTP с правами 0644 (так клиенты обычно и загружают), другая сторона может читать и удалять, но не переписать на месте: маска ACL ограничивает права до групповых битов файла. Для обмена «положил — забрали» этого достаточно. Если нужно править файлы друг друга на месте, mp site fix <домен> пересчитывает маски у всего, что уже лежит в папке.
  • mp site fix знает про общие папки: после пересчёта ACL всего дерева сайта он возвращает записи гостей.
  • Переезд между панелями общие папки не переносит: файлы уезжают вместе с сайтом, а папку гостю на новом сервере выдают заново той же командой.

4. Что не делать

  • Не менять home гостя вручную в /etc/passwd — см. начало страницы.
  • Не давать папку без --no-php тому, кому не доверяете писать код от имени сайта.
  • Не выдавать корень docroot целиком: гость получит запись во весь сайт, включая bitrix/ и .settings.php. Для правки самого сайта подрядчику нужен не гость, а аккаунт с доступом к сайту.
Исходник страницы на GitHub