Якщо вам потрібно дати клієнтам або колегам доступ лише до обміну файлами через SFTP, але без можливості shell‑логіну — найкращий шлях це chroot‑ізоляція в OpenSSH. Нижче я покажу, як на сервер Linux налаштувати безпечний SFTP‑jail, які встановити права доступу Linux, як протестувати SSH підключення і як акуратно відкотити всі зміни, якщо щось піде не так. Обіцяю, все буде по кроках і зрозуміло 😊

Передумови та план

Вам знадобляться права root або sudo, встановлений OpenSSH (sshd) та доступ до термінал Linux. План такий:

  • Створити групу sftpusers і додати туди користувачів (без shell).
  • Підготувати chroot‑каталоги з правильними власниками та правами.
  • Налаштувати sshd_config на internal-sftp з Match‑блоком.
  • Перевірити конфіг і перезапустити службу.
  • Протестувати клієнтом sftp.
  • Знати, як швидко відкотитися.

Основний How‑to: безпечний SFTP chroot

1) Створіть групу для SFTP‑користувачів

sudo groupadd sftpusers

Ми використаємо Match group у sshd_config, щоб застосувати політики лише до цієї групи. Це зручно, якщо на сервері вже є інші користувачі з повноцінним shell.

2) Додайте користувача без shell‑доступу

Створимо користувача з домашнім каталогом усередині майбутнього chroot і з оболонкою nologin:

# приклад з ім'ям клієнта: acme
sudo useradd -m -d /sftp/acme -s /usr/sbin/nologin -g sftpusers acme
# встановити (або вимкнути) пароль, якщо треба парольну автентифікацію
sudo passwd acme

Порада: краще використовувати ключі SSH замість паролів, але нижче я покажу обидва варіанти.

3) Підготуйте структуру каталогів і права

Для chroot є жорстка вимога: ChrootDirectory і всі його батьківські директорії мають належати root і не бути записуваними користувачем. Файли для завантаження зберігайте у підкаталозі, що належить користувачу.

# створимо базу для користувача
sudo mkdir -p /sftp/acme
sudo chown root:root /sftp/acme
sudo chmod 755 /sftp/acme

# робоча текa для завантаження/вивантаження файлів
sudo mkdir -p /sftp/acme/uploads
sudo chown acme:sftpusers /sftp/acme/uploads
sudo chmod 750 /sftp/acme/uploads

Тепер acme зможе писати лише в uploads, а корінь chroot залишиться контрольованим root. Це критично для безпеки.

4) Налаштуйте ключі SSH (рекомендовано)

# створити каталог для ключів усередині домашньої теки користувача
sudo -u acme mkdir -p /sftp/acme/.ssh
sudo chmod 700 /sftp/acme/.ssh

# додати публічний ключ до authorized_keys
# (замініть 'YOUR_PUBLIC_KEY' на реальний вміст id_ed25519.pub або id_rsa.pub)
echo "YOUR_PUBLIC_KEY" | sudo tee /sftp/acme/.ssh/authorized_keys > /dev/null
sudo chown -R acme:acme /sftp/acme/.ssh
sudo chmod 600 /sftp/acme/.ssh/authorized_keys

Якщо ви плануєте лише ключову автентифікацію, далі вимкнемо паролі для цієї групи.

5) Резервна копія та правки sshd_config

sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak-$(date +%F)

# відкрийте файл у улюбленому редакторі
sudo nano /etc/ssh/sshd_config

Знайдіть рядок із Subsystem sftp та замініть на internal-sftp:

Subsystem sftp internal-sftp -f AUTH -l VERBOSE

Додайте Match‑блок для нашої групи (вкінці файлу):

Match Group sftpusers
    ChrootDirectory /sftp/%u
    ForceCommand internal-sftp
    X11Forwarding no
    AllowTcpForwarding no
    PasswordAuthentication no

Опція PasswordAuthentication no робить SSH підключення для цієї групи тільки по ключам. Якщо вам потрібні паролі — приберіть цей рядок або поставте yes (але зважайте на безпеку).

6) Перевірте конфіг і перезапустіть sshd

# валідація синтаксису
sudo sshd -t

# якщо помилок немає, застосуйте зміни
sudo systemctl reload sshd
# або
sudo systemctl restart sshd

Про всяк випадок тримайте відкритим ще одне активне SSH‑вікно під адміном, щоб не втратити доступ 😅

7) Тестуємо SFTP

# приклад із ключем
sftp -i ~/.ssh/id_ed25519 acme@your.server

# перевірте, що після логіну ви бачите лише /
# і можете писати в /uploads
put локальний_файл /uploads/
ls -la /uploads

Якщо все окей — вітаю! Ви зробили чистий SFTP‑jail із правильними правами доступу Linux для ваших користувачів та груп Linux.

Альтернативні варіанти

  • Початкова текa: додайте в Match ForceCommand internal-sftp -d /uploads, щоб користувач потрапляв прямо в робочу теку.
  • Спільний простір для команди: замість /sftp/%u використайте /sftp/shared і керуйте доступом через групи та umask/ACL.
  • AuthorizedKeys поза chroot: додайте AuthorizedKeysFile /etc/ssh/authorized_keys/%u і зберігайте ключі там (тільки root:root, 600).
  • Журнали SFTP: ми вже додали -f AUTH -l VERBOSE до Subsystem — шукайте події в auth.log або journalctl.

GUI‑спосіб (Webmin або Cockpit)

Якщо вам зручніше з GUI, використайте Webmin або Cockpit:

  1. Встановіть Webmin або підключіть Cockpit до сервера.
  2. Через модуль Users створіть користувача acme, додайте до групи sftpusers, як shell виберіть /usr/sbin/nologin.
  3. Створіть /sftp/acme і /sftp/acme/uploads, виставте права як у кроках вище.
  4. В модулі для SSH (або через редагування файлів у GUI) змініть sshd_config на internal-sftp та додайте Match‑блок.
  5. Перезапустіть sshd із GUI і протестуйте SFTP‑клієнтом (наприклад, FileZilla або WinSCP).

Відкат змін (rollback)

Якщо потрібно все повернути назад:

# 1) Повернути резервну копію конфіга
sudo cp /etc/ssh/sshd_config.bak-YYYY-MM-DD /etc/ssh/sshd_config
sudo sshd -t && sudo systemctl reload sshd

# 2) Видалити користувача з групи або повністю
sudo gpasswd -d acme sftpusers
# або повне видалення з домашньою текою (уважно!)
sudo userdel -r acme

# 3) Прибрати директори, якщо більше не потрібні
sudo rm -rf /sftp/acme

# 4) За потреби видалити групу
sudo groupdel sftpusers

Переконайтеся, що не залежите від цих користувачів у скриптах/інтеграціях, перш ніж видаляти їх.

FAQ

Чому SFTP логін відхиляється з помилкою “bad ownership or modes”?
Перевірте: /sftp і /sftp/<user> мають бути root:root і не записувані користувачем (chmod 755). Файл authorized_keys600, каталог .ssh700.

Користувач не може писати файли.
Забули створити підкаталог на запис, наприклад uploads, і передати йому власника user:sftpusers з правами 750 або 770 для спільної роботи.

Потрібен і shell, і SFTP одному користувачу.
Не додавайте його до sftpusers. Match‑блок спрацює лише для групи. Або зробіть окрему групу/окремий Match User з потрібною політикою.

Як розшарити одну теку між кількома користувачами?
Використовуйте спільну групу, наприклад sftpteam, і встановіть chgrp sftpteam /sftp/shared/uploads, chmod 2770 (setgid), щоб нові файли успадковували групу.

SELinux або AppArmor заважають?
На системах із SELinux: відновіть контексти sudo restorecon -Rv /sftp. Для AppArmor зазвичай додаткових правил не потрібно, якщо використовується internal-sftp.

Як отримати більш детальне логування SFTP?
Ми вже задали -l VERBOSE у Subsystem. Переглядайте sudo journalctl -u sshd або /var/log/auth.log.

Порада від Kernelka

Перш ніж міняти бойову конфігурацію, перевірте сценарій на тестовому інстансі або в контейнері. Завжди тримайте окреме активне адмінське SSH підключення під час перезапуску sshd. А ще — використовуйте ключі з паролем і Fail2ban для підсилення безпеки. Маленькі обережності економлять великі нерви 😉

Підсумок

  • Створили групу sftpusers і користувача без shell.
  • Підготували chroot‑каталоги з правильними правами (root:root у корені, запис лише у підкаталог).
  • Налаштували internal-sftp і Match‑блок у sshd_config.
  • Перевірили конфіг, перезапустили sshd і протестували SFTP‑клієнтом.
  • Знаємо альтернативи (початкова текa, спільні групи) та як зробити безпечний відкат.