Безопасность серверов 14 мин чтения 2026-10-16

Изоляция SFTP в Chroot Jail на Linux VDS: безопасный доступ к файлам сайта без шелла SSH и риска чтения чужих каталогов

Как безопасно изолировать доступ подрядчиков и разработчиков к файлам сайта через OpenSSH Chroot Jail: настройка без шелла, устранение сбоев bad ownership, интеграция с Nginx и авторизация по ключам.

Инженерная редакция SysKit Проверено инженерами SysKit.ru

В практике каждого вебмастера, тимлида или системного администратора наступает момент, когда к файлам одного конкретного сайта на VDS требуется предоставить доступ стороннему исполнителю: верстальщику, контент-менеджеру, SEO-специалисту или внешнему подрядчику. Классическая ошибка начинающих администраторов — создать стандартного пользователя Linux с паролем и отправить данные для входа по SSH.

Такой подход создает колоссальную брешь в безопасности сервера. Получив стандартный SSH-терминал, пользователь может свободно перемещаться по файловой системе вверх по дереву каталогов (cd ..), просматривать соседние проекты в /var/www/, читать конфигурационные файлы .env и wp-config.php с открытыми паролями к боевым базам данных, анализировать список активных процессов через ps aux и даже компилировать сторонний софт. С другой стороны, установка устаревших демонов вроде vsftpd или ProFTPD усложняет стек, требует открытия дополнительных диапазонов пассивных портов и нередко передает учетные данные в открытом незашифрованном виде.

Стандартом надежной изоляции в современных дистрибутивах Linux (Ubuntu 22.04 / 24.04 LTS, Debian 12) является использование встроенного механизма OpenSSH Chroot Jail с подсистемой internal-sftp. В этом руководстве мы разберем правильную настройку изолированного окружения: без доступа к шеллу, с корректными правами под веб-сервер Nginx/Apache, поддержкой SSH-ключей Ed25519 и разбором распространенных ошибок конфигурации.

1. Риски обычного SSH-доступа: почему подрядчикам нельзя давать терминал сервера

Когда вы создаете обычную учетную запись в Linux через команду adduser или useradd со стандартной оболочкой /bin/bash, операционная система предоставляет пользователю права на чтение большинства системных директорий. Права POSIX по умолчанию позволяют любому непривилегированному пользователю видеть то, что ему категорически не положено знать в среде shared-хостинга нескольких проектов:

  • Компрометация соседних сайтов: Достаточно выполнить команду cat /var/www/client2/.env или прочитать wp-config.php, чтобы получить реквизиты доступа к MySQL/PostgreSQL, секретные ключи сессий, API-токены эквайринга и Telegram-ботов.
  • Разведка инфраструктуры: Через команды ss -tulpn, cat /etc/passwd и ip a злоумышленник или недобросовестный подрядчик может собрать полный профиль сервера: внутренние порты контейнеров, имена баз данных и конфигурацию локальных сервисов.
  • Неконтролируемый запуск процессов: Доступ к шеллу позволяет запускать фоновые скрипты, туннели, утилиты сканирования сети или скрытые майнеры в каталоге /tmp.
Критерий безопасности Обычный доступ по SSH Классический FTP (vsftpd) OpenSSH Chroot Jail
Шифрование трафика Да (SSHv2) Нет по умолчанию (FTP — открытый текст; FTPS требует сложной настройки TLS и портов) Да (SSHv2 / SFTP из коробки)
Доступ к терминалу (Shell) Полный bash/sh Отсутствует Заблокирован (/usr/sbin/nologin)
Выход за пределы каталога Свободный (видит всю ФС) Зависит от конфигурации Исключен (для непривилегированного пользователя без шелла)
Сетевые порты Порт 22 Порт 21 + диапазон пассивных портов Только штатный порт SSH (22)
Нагрузка на стек Штатный sshd Отдельный тяжелый сервис Минимальная (используется штатный демон sshd без доп. сервисов)

2. Механизм Chroot Jail в OpenSSH: преимущества internal-sftp перед сторонними демонами

Концепция Chroot (Change Root) — это системный вызов ядра Linux, который изменяет корневую директорию для текущего процесса и всех его потомков. Когда клиент авторизуется в системе, его корневой каталог / принудительно перенаправляется, например, в /var/www/site_user. Все системные папки (/bin, /etc, /home, /var/log) для него перестают существовать — пользователь физически не может подняться выше точки своего чрута.

Исторически настройка Chroot для SSH требовала копирования системных библиотек, создания фиктивных устройств /dev/null, /dev/zero и наличия бинарника /usr/lib/openssh/sftp-server внутри каждой изолированной директории. Если обновлялась системная библиотека glibc, чруты ломались.

Современный OpenSSH полностью решил эту проблему внедрением механизма internal-sftp. В отличие от внешнего бинарника, internal-sftp исполняется непосредственно внутри адресного пространства самого демона sshd. Ему не нужны никакие служебные файлы, библиотеки или интерпретаторы команд внутри изолированного каталога. Демон выполняет системный вызов chroot() сразу после успешной аутентификации и переходит к обслуживанию файловых запросов SFTP.

💡 Совет инженера: фундаментальное правило безопасности OpenSSH

Чтобы исключить возможность локального повышения привилегий через замену бинарников или создание жестких ссылок, OpenSSH на уровне исходного кода требует жесткого соблюдения правила: каталог chroot и абсолютно все родительские папки в пути обязаны принадлежать пользователю root и иметь права не более 755. Ни группа, ни сам пользователь не должны иметь права на запись в корневую папку чрута.

3. Создание группы sftpusers и учетной записи без шелла входа

Для удобного администрирования разграничение доступа строится на базе отдельной системной группы (например, sftpusers). Все пользователи, входящие в эту группу, автоматически подпадают под изолирующие правила в конфигурации SSH.

Подключитесь к вашему серверу по SSH под пользователем с привилегиями sudo и создайте системную группу:

# Создаем группу для изолированных пользователей SFTP
sudo groupadd sftpusers

Теперь создадим пользователя (например, devclient) с блокировкой командной оболочки. В качестве шелла входа укажем /usr/sbin/nologin, а домашней директорией назначим будущий корень его чрута /var/www/devclient:

⚠️ Почему флаг -m категорически нельзя использовать

При использовании стандартного флага useradd -m система автоматически создает домашний каталог с владельцем devclient:devclient и копирует шаблоны .bashrc из /etc/skel. Если такой каталог указать в качестве ChrootDirectory, подключение будет мгновенно заблокировано с ошибкой fatal: bad ownership or modes, так как корень чрута обязан принадлежать строго root:root. Поэтому каталог создается и настраивается вручную на шаге 5.

# Создаем пользователя без интерактивного шелла
# Флаг -g задает основную группу sftpusers
# Флаг -G добавляет вторичную группу www-data (для веб-сервера)
# Флаг -s блокирует bash/sh оболочку
# Флаг -d задает домашнюю директорию изолированного окружения (без -m!)
sudo useradd -g sftpusers -G www-data -d /var/www/devclient -s /usr/sbin/nologin devclient

# Задаем надежный пароль для учетной записи
sudo passwd devclient

💡 Совет инженера: криптостойкие пароли

При использовании парольной аутентификации для SFTP категорически избегайте простых комбинаций, словарных слов и дат. Брутфорс-боты непрерывно сканируют порт 22. Сгенерируйте случайный 20-значный пароль через онлайн-инструмент Генератор надежных паролей SysKit и обязательно используйте Fail2ban.

4. Конфигурация sshd_config: директивы Match Group, ChrootDirectory и запрет туннелей

В современных версиях дистрибутивов Ubuntu 22.04 / 24.04 LTS и Debian 12 конфигурация OpenSSH поддерживает модульную структуру каталога /etc/ssh/sshd_config.d/. Это позволяет вынести настройки изолированных SFTP-клиентов в отдельный файл, не затрагивая основной файл /etc/ssh/sshd_config.

Сначала убедитесь, что в качестве подсистемы SFTP указан встроенный обработчик internal-sftp. Откройте или проверьте основной конфиг:

# Проверяем директиву Subsystem в /etc/ssh/sshd_config
sudo grep -i "Subsystem sftp" /etc/ssh/sshd_config

Если там указан внешний путь Subsystem sftp /usr/lib/openssh/sftp-server, закомментируйте его и укажите Subsystem sftp internal-sftp. Затем создайте отдельный конфигурационный файл для группы sftpusers:

sudo nano /etc/ssh/sshd_config.d/sftp-chroot.conf

Вставьте следующий блок директив:

# Изоляция группы пользователей SFTP
Match Group sftpusers
    # Директория Chroot: переменная %u подставляет имя текущего пользователя
    ChrootDirectory /var/www/%u

    # Принудительный запуск internal-sftp:
    # -u 0002: маска прав (файлы 664, каталоги 775)
    # -d /public_html: автоматический переход в рабочий каталог сайта при входе
    ForceCommand internal-sftp -u 0002 -d /public_html

    # Блокировка интерактивного терминала (PTY)
    PermitTTY no

    # Комплексный запрет всех видов туннелей (TCP, X11, Agent, StreamLocal)
    DisableForwarding yes

    # Сохраняем парольную аутентификацию для доступа без терминала
    PasswordAuthentication yes

⚠️ Важное предупреждение: порядок секций Match

Директива Match в OpenSSH действует до конца конфигурационного файла либо до следующей секции Match. Все общие директивы демона должны располагаться строго до блоков Match, иначе они будут применены исключительно к соответствующей группе или пользователю.

Перед применением настроек обязательно протестируйте синтаксис конфигурации. Затем примените изменения через перечитывание конфигурации (reload), которое безопасно для активных соединений:

# 1. Тестирование синтаксиса SSH (вывод должен быть пустым)
sudo sshd -t

# 2. Перезагрузка конфигурации без разрыва существующих сессий
sudo systemctl reload ssh

# При необходимости полного перезапуска службы:
sudo systemctl restart ssh

💡 Почему reload надежнее restart

Команда systemctl reload ssh отправляет главному процессу сигнал SIGHUP. OpenSSH мгновенно перечитывает конфигурационные файлы и применяет новые правила к каждому новому подключению без разрыва вашей текущей административной сессии. В Ubuntu 24.04 LTS это также исключает рассинхронизацию с сокетом ssh.socket.

5. Архитектура каталогов: жесткое разделение корня root:root и папки public_html

Основная сложность настройки Chroot в Linux заключается в архитектурном противоречии: OpenSSH требует, чтобы точка входа в чрут принадлежала root:root и была закрыта на запись для всех остальных, но пользователю требуется возможность загружать файлы на сервер.

Решением является двухуровневая структура каталогов:

  • /var/www/devclient — корень Chroot Jail. Принадлежит строго root:root с правами 755. Пользователь не может создавать или удалять файлы в этой папке.
  • /var/www/devclient/public_html — рабочий каталог сайта. Принадлежит devclient:www-data с правами 2775. Сюда пользователь загружает код, а веб-сервер имеет права на чтение и запись.

Создадим правильную структуру и выставим корректные права владения:

# 1. Создаем корневой каталог чрута и вложенную папку веб-документов
sudo mkdir -p /var/www/devclient/public_html

# 2. Назначаем владельцем корня суперпользователя root (КРИТИЧЕСКИ ВАЖНО)
sudo chown root:root /var/www/devclient
sudo chmod 755 /var/www/devclient

# 3. Назначаем рабочий каталог сайта пользователю и группе веб-сервера
sudo chown devclient:www-data /var/www/devclient/public_html

# 4. Устанавливаем права 2775 с битом SGID (chmod g+s)
sudo chmod 2775 /var/www/devclient/public_html

💡 Совет инженера: зачем нужен SGID-бит (права 2775)

Бит SGID (Special Group ID, первая цифра 2 в chmod 2775) заставляет операционную систему автоматически присваивать группу www-data абсолютно всем новым файлам и вложенным подкаталогам, которые создаст пользователь через SFTP-клиент. Без SGID новые файлы создавались бы с первичной группой пользователя (sftpusers), из-за чего Nginx или Apache не смогли бы получить к ним доступ.

6. Совместная работа с Nginx и Apache: права группы www-data и флаг umask

Чтобы сайт корректно открывался в браузере, а CMS (WordPress, Bitrix, Laravel) могла создавать кэш и сохранять загруженные медиафайлы, веб-сервер и SFTP-пользователь должны работать слаженно без конфликта прав доступа.

Пример корректного виртуального хоста Nginx для изолированного пользователя:

server {
    listen 80;
    server_name client.example.com;

    # Указываем путь к рабочей папке public_html внутри чрута
    root /var/www/devclient/public_html;
    index index.php index.html;

    access_log /var/log/nginx/devclient_access.log;
    error_log /var/log/nginx/devclient_error.log;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
    }

    # Разрешаем запросы для SSL-сертификатов Let's Encrypt (ACME challenge)
    location ^~ /.well-known/ {
        allow all;
    }

    # Запрет доступа к скрытым системным файлам (.env, .git)
    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }
}

Обратите внимание на значение флага -u 0002 в директиве ForceCommand internal-sftp -u 0002: маска создания файлов 0002 гарантирует, что создаваемые клиентом файлы будут получать права 664 (чтение и запись для владельца и группы www-data), а папки — права 775. Если веб-сервер попытается обновить кэш или плагин, он не столкнется с ошибкой 403 Forbidden.

7. Требования к серверу и выбор VDS для клиентских сайтов

При одновременной работе нескольких изолированных SFTP-пользователей на одном сервере ключевое значение приобретают аппаратные параметры дисковой подсистемы и процессора:

  • Дисковая подсистема и IOPS: Синхронизация каталогов CMS (WordPress, Bitrix) включает тысячи мелких файлов. Высокие показатели произвольного чтения/записи (IOPS) на NVMe-накопителях исключают задержки и блокировки потоков при передаче данных.
  • Нагрузка на шифрование (CPU): Каждая активная SFTP-сессия осуществляет шифрование трафика алгоритмами AES-GCM или ChaCha20-Poly1305. Для серверов с несколькими параллельными сессиями разработчиков рекомендуется запас по тактовой частоте процессора и минимум 2 vCPU.
  • Резервное копирование: Изоляция в Chroot предотвращает выход за пределы домашнего каталога, но не защищает от случайного удаления данных внутри public_html самим пользователем. Наличие регулярных снапшотов на уровне хостинга позволяет быстро восстановить сайт в случае ошибок подрядчика.

Для надежного развертывания веб-проектов и стабильной работы служб можно ориентироваться на проверенные конфигурации виртуальных серверов:

Рекомендуемые VDS-провайдеры

Отказоустойчивые сервера с быстрыми NVMe и каналом до 1 Гбит/с

Выбор редакции
⚡

Timeweb Cloud — Быстрые NVMe VDS

Высокочастотные процессоры 3.3+ ГГц для быстрой компиляции и отдачи страниц, NVMe-накопители и отказоустойчивая сеть 1 Гбит/с.

Конфигурация
1 vCPU 3.3 ГГц • 1 ГБ RAM • 15 ГБ NVMe • Трафик без лимита
Премиум Tier III
🔷

Selectel — Надежные облачные серверы

Корпоративная инфраструктура в сертифицированных ЦОД уровня Tier III с гарантированными ресурсами и гибким управлением приватными сетями.

Конфигурация
2 vCPU • 2 ГБ RAM • 30 ГБ NVMe • Дата-центры Tier III
Простота и стабильность
🟠

Beget — Простота для веб-разработчиков

Мгновенное развертывание чистой Ubuntu 24.04 LTS, удобный файловый менеджер в панели, автоматические ежедневные бэкапы и поддержка 24/7.

Конфигурация
1 vCPU • 1 ГБ RAM • 15 ГБ NVMe • Бесплатные бэкапы

8. Авторизация по ключам Ed25519 в изолированной Chroot-среде

Хотя надежный пароль достаточен для большинства задач контент-менеджеров, подключение по криптографическим SSH-ключам алгоритма Ed25519 обеспечивает максимальную защиту от перехвата и брутфорс-атак. Однако при использовании Chroot возникает вопрос: куда положить открытый ключ клиента?

Так как корень чрута /var/www/devclient принадлежит root:root и закрыт на запись, сам пользователь не может создать папку .ssh или загрузить туда ключ. Для решения этой задачи в production-средах применяются два подхода:

Способ 1: Централизованное хранение ключей в /etc/ssh/authorized_keys (Рекомендуемый)

В секцию Match Group sftpusers конфигурации OpenSSH добавляется директива, указывающая системный каталог для открытых ключей:

Match Group sftpusers
    ChrootDirectory /var/www/%u
    ForceCommand internal-sftp -u 0002
    # Путь к открытым ключам изолированных пользователей
    AuthorizedKeysFile /etc/ssh/authorized_keys/%u

Создайте директорию на сервере и добавьте открытый ключ клиента:

# Создаем системную директорию для хранения ключей
sudo mkdir -p /etc/ssh/authorized_keys
sudo chmod 755 /etc/ssh/authorized_keys

# Создаем файл ключа для пользователя devclient
sudo nano /etc/ssh/authorized_keys/devclient

# Вставляем открытый ключ клиента (начинается на ssh-ed25519 ...)
# Выставляем строгие права (только чтение суперпользователем)
sudo chown root:root /etc/ssh/authorized_keys/devclient
sudo chmod 644 /etc/ssh/authorized_keys/devclient

Этот метод исключает засорение рабочей папки сайта служебными каталогами .ssh и предотвращает случайное удаление ключа самим клиентом через графический SFTP-клиент.

Способ 2: Размещение папки .ssh внутри корня чрута

Если вы хотите сохранить стандартный путь, создайте папку .ssh вручную от имени суперпользователя:

sudo mkdir -p /var/www/devclient/.ssh
sudo nano /var/www/devclient/.ssh/authorized_keys

# Устанавливаем строгие права: владельцем ОБЯЗАН оставаться root
sudo chown -R root:root /var/www/devclient/.ssh
sudo chmod 755 /var/www/devclient/.ssh
sudo chmod 644 /var/www/devclient/.ssh/authorized_keys

9. Траблшутинг: решение ошибки bad ownership or modes for chroot directory

Если при попытке подключения в WinSCP, FileZilla или через консольный sftp соединение мгновенно разрывается, первым шагом изучите системный журнал авторизации на сервере:

# Просмотр системного лога службы SSH в реальном времени
sudo journalctl -u ssh -e --no-pager
Сообщение в логе / Ошибка Причина сбоя Способ решения
fatal: bad ownership or modes for chroot directory Каталог Chroot (или один из родительских каталогов) принадлежит пользователю, а не root, либо имеет права на запись для группы (775 или 777). Выполните:
sudo chown root:root /var/www/devclient
sudo chmod 755 /var/www/devclient
subsystem: cannot stat /usr/lib/.../sftp-server В конфиге указан внешний бинарник sftp-server, которого нет внутри изолированного чрута. Замените директиву в sshd_config на встроенную: Subsystem sftp internal-sftp.
Permission denied (publickey,password) Неверный пароль, отключена директива PasswordAuthentication yes в блоке Match, или заблокирован порт. Проверьте открыт ли порт SSH и обновите пароль через sudo passwd devclient.
Клиент не может создать файл в корне Пользователь пытается писать в корень чрута /var/www/devclient, закрытый для записи. Загружайте файлы в папку public_html. Для автоматического открытия этой папки укажите флаг -d /public_html в директиве ForceCommand.

10. Готовый скрипт автоматического создания изолированного пользователя

Чтобы не выполнять команды настройки вручную для каждого нового клиента или подрядчика, создайте надежный bash-скрипт автоматизации create_sftp_user.sh:

#!/usr/bin/env bash
# Скрипт автоматического создания изолированного SFTP-пользователя в Chroot Jail
set -euo pipefail

if [ "$EUID" -ne 0 ]; then
  echo "❌ Ошибка: скрипт должен быть запущен с правами root (sudo)!"
  exit 1
fi

USERNAME="${1:-}"
if [ -z "$USERNAME" ]; then
  echo "Использование: sudo $0 <имя_пользователя>"
  exit 1
fi

BASE_DIR="/var/www/$USERNAME"
WEB_DIR="$BASE_DIR/public_html"

# 1. Проверяем наличие группы sftpusers
if ! getent group sftpusers > /dev/null 2>&1; then
  groupadd sftpusers
  echo "✅ Создана системная группа sftpusers"
fi

# 2. Создаем пользователя, если он еще не существует
if id "$USERNAME" > /dev/null 2>&1; then
  echo "⚠️ Пользователь $USERNAME уже существует, обновляем группы и каталоги..."
  # Флаг -aG добавляет вторичную группу www-data, не затирая существующие группы пользователя
  usermod -g sftpusers -aG www-data -s /usr/sbin/nologin -d "$BASE_DIR" "$USERNAME"
else
  useradd -g sftpusers -G www-data -d "$BASE_DIR" -s /usr/sbin/nologin "$USERNAME"
  echo "✅ Пользователь $USERNAME успешно зарегистрирован в системе"
fi

# 3. Формируем безопасную структуру каталогов
mkdir -p "$WEB_DIR"

# Корень чрута ОБЯЗАН принадлежать root:root с правами 755
chown root:root "$BASE_DIR"
chmod 755 "$BASE_DIR"

# Рабочий каталог сайта передаем пользователю и веб-серверу с SGID-битом
chown "$USERNAME":www-data "$WEB_DIR"
chmod 2775 "$WEB_DIR"

echo "--------------------------------------------------------"
echo "🎉 Изолированный SFTP Chroot успешно настроен для: $USERNAME"
echo "📂 Корень Chroot: $BASE_DIR (права 755, владелец root:root)"
echo "🌐 Каталог сайта: $WEB_DIR (права 2775, $USERNAME:www-data)"
echo "--------------------------------------------------------"
echo "Установите пароль для пользователя командой:"
echo "sudo passwd $USERNAME"
echo "--------------------------------------------------------"

Сохраните скрипт на сервере (например, в /usr/local/bin/create_sftp_user.sh) и сделайте его исполняемым:

sudo chmod +x /usr/local/bin/create_sftp_user.sh

# Запуск для нового клиента:
sudo /usr/local/bin/create_sftp_user.sh client_shop

11. Резюме и итоговый чек-лист безопасности

Использование встроенного механизма OpenSSH Chroot Jail позволяет полностью изолировать внешних подрядчиков, верстальщиков и клиентов в пределах их собственного сайта, гарантируя конфиденциальность соседних проектов и системных конфигураций VDS.

📋 Чек-лист безопасности администратора перед передачей доступа

  • Пользователю назначен шелл /usr/sbin/nologin (интерактивный вход в консоль заблокирован).
  • Каталог Chroot (/var/www/username) принадлежит строго root:root с правами не выше 755.
  • В рабочей папке public_html установлены права 2775 с SGID-битом и группой www-data.
  • В секции Match Group заданы директивы ForceCommand internal-sftp -u 0002 -d /public_html, DisableForwarding yes и PermitTTY no.
  • Синтаксис проверен командой sudo sshd -t, а служба перезагружена через sudo systemctl reload ssh.
  • Учетная запись защищена криптостойким паролем или SSH-ключом Ed25519, а порт закрыт от брутфорса через Fail2ban или CrowdSec.

Настройте защищенный VDS с быстрыми NVMe-дисками

Разверните надежный облачный сервер на базе Ubuntu 24.04 LTS у проверенных провайдеров. Быстрые диски NVMe обеспечат мгновенную передачу файлов по SFTP и комфортную работу клиентов без задержек.

Инструменты SysKit по теме статьи

Бесплатные утилиты для проверки и диагностики вашего сервера

Вопросы и ответы (FAQ)

Популярные вопросы вебмастеров и сисадминов по данной теме

Почему клиент при подключении получает ошибку «fatal: bad ownership or modes for chroot directory»?
Демон OpenSSH из соображений безопасности категорически требует, чтобы каталог, указанный в директиве ChrootDirectory, а также абсолютно все его родительские папки вплоть до корня файловой системы (/), принадлежали суперпользователю root:root и не имели прав на запись для группы или других пользователей (максимум chmod 755). Если директория принадлежит самому пользователю или имеет права chmod 775/777, OpenSSH мгновенно сбрасывает TCP-сессию.
Может ли пользователь в Chroot Jail открыть bash-терминал или выполнить системную команду?
Нет. Во-первых, системная оболочка пользователя на уровне системы заменяется на /usr/sbin/nologin (или /bin/false). Во-вторых, директива ForceCommand internal-sftp принудительно перехватывает любое входящее соединение и запускает исключительно протокол передачи файлов SFTP, блокируя запуск любых интерактивных PTY-сессий и шеллов.
Почему веб-сервер Nginx выдает ошибку 403 Forbidden на файлы, загруженные по SFTP?
По умолчанию демон SFTP создает файлы с маской umask 022, что дает права 644 (запрет записи для группы). Кроме того, если рабочий каталог сайта не имеет SGID-бита (chmod 2775), создаваемые файлы наследуют первичную группу пользователя (sftpusers), из-за чего веб-сервер www-data не может их модифицировать. Чтобы веб-сервер и PHP могли беспрепятственно работать с загруженными файлами, в директиве ForceCommand задается флаг «-u 0002» (создание файлов 664 и каталогов 775), пользователь добавляется во вторичную группу www-data, а на каталог сайта устанавливается бит SGID.
Как предоставить доступ по публичному SSH-ключу, если корень чрута закрыт на запись?
Поскольку корень chroot принадлежит root:root (755), пользователь не может самостоятельно создать или изменить файл .ssh/authorized_keys. Рекомендуемый инженерный подход — вынести хранение публичных ключей за пределы домашней папки пользователя через директиву «AuthorizedKeysFile /etc/ssh/authorized_keys/%u» в блоке Match Group. Проверка открытого ключа демоном sshd происходит на этапе аутентификации до вызова chroot(), права 644 на файл ключа под root:root полностью соответствуют требованиям StrictModes, а клиент не сможет случайно повредить свой ключ через SFTP.

Читайте также в блоге SysKit

Смежные руководства и полезные технические статьи