Для сайту на хостингу ставте каталогам права 755, файлам 644, а wp-config.php 600 або 640. Власником усіх файлів має бути ваш користувач хостингу, і це важить не менше за самі цифри. Права 777 не потрібні ніколи: на нашому стенді PHP-файл, який інший користувач сервера підкинув у каталог 777, виконувався від імені власника сайту і міг переписати будь-який файл.
Як ми перевіряли
10 листопада 2026 року на тестовому стенді: контейнер Ubuntu 24.04.5, nginx 1.24.0 перед Apache 2.4.58, окремо nginx без Apache, PHP-FPM 8.3.6 у двох варіантах (пул від імені власника сайту, як зазвичай на віртуальному хостингу, і пул від www-data), MariaDB 10.11.14, WordPress 6.4.3 (2777 файлів, 284 каталоги). Ми змінювали права і власників, перевіряли відповіді curl, логи та поведінку WordPress, пробували писати в каталоги сайту від імені іншого користувача сервера і заміряли час масового виправлення прав. Це поведінка тестового сервера, а не дані з серверів RichHost.
Як читати права: три цифри для трьох категорій
Кожен файл має власника, групу і окремі права для трьох категорій: власника, групи і всіх інших. Право читання дорівнює 4, запису 2, виконання 1, а цифра є їхньою сумою: 7 означає rwx, 6 означає rw, 5 означає r і x, 4 лише читання, 0 нічого. Перша цифра стосується власника, друга групи, третя всіх інших. Права і власника у вигляді цифр показує команда:
$ stat -c '%a %U:%G %n' wp-config.php index.php wp-content 600 cw8site:cw8site wp-config.php 644 cw8site:cw8site index.php 755 cw8site:cw8site wp-content
Для каталогу ті самі літери означають інше: r дозволяє бачити список файлів, w створювати, перейменовувати і видаляти файли в ньому, x заходити в каталог і відкривати файли, ім’я яких відоме. Тому каталогам потрібен біт x, а звичайним файлам сайту ні: PHP-скрипт не запускається як програма, його читає інтерпретатор. І ще одна деталь, яку ми побачимо в тестах: видалити або перейменувати файл може кожен, хто має право запису в каталог, навіть якщо сам файл йому не належить.
Таблиця: права, хто що може і коли їх ставити
Перевірено на стенді, де файли належать користувачу сайту, а nginx і Apache працюють від www-data. Для вебсервера ваші файли потрапляють у категорію «інші», тому третя цифра вирішує, чи віддасть він картинку або стиль.
| Права | Хто що може | Коли використовувати |
|---|---|---|
| 755, каталог | Власник створює і видаляє файли, вебсервер та інші лише заходять і читають | Усі каталоги сайту |
| 711, каталог | Інші заходять, але не бачать списку файлів; картинки з такого каталогу віддавались з кодом 200 | Домашній каталог або каталог, список файлів якого не варто показувати |
| 750 або 700, каталог | Вебсервер не заходить: Apache відповів 403, nginx передав запит WordPress | Лише каталоги поза кореневою папкою сайту: бекапи, приватні дані |
| 644, файл | Власник змінює, усі інші читають | Усі файли сайту: PHP, HTML, CSS, зображення, .htaccess |
| 640, файл | Власник змінює, група читає, інші не мають доступу | wp-config.php, коли PHP працює від www-data і файл має групу www-data |
| 600, файл | Лише власник; картинка дає 403, PHP-файл при PHP від власника працює | wp-config.php, .env, бекапи, приватні ключі |
| 400 або 440, файл | Лише читання, змінити файл не може навіть PHP власника | wp-config.php, якщо треба заборонити скриптам його змінювати |
| 666, файл | Будь-який користувач сервера дописує або переписує файл | Ніколи |
| 777, каталог або файл | Будь-хто створює, видаляє і підміняє файли | Ніколи, навіть для uploads і cache |
Від чийого імені працює PHP: власник чи www-data
Ті самі права дають різний результат залежно від того, від якого користувача працює PHP. На віртуальному хостингу кожен пул PHP-FPM зазвичай запускається від імені власника домену: у конфігурації пулу user збігається з власником, а група сокета www-data. На старих конфігураціях і на власних серверах PHP часто працює від www-data, як і вебсервер.
Перевірити це можна невеликим файлом. Покладіть його в кореневу папку сайту, відкрийте в браузері і одразу видаліть:
<?php echo posix_getpwuid(posix_geteuid())['name'], "\n"; echo is_writable(__DIR__ . '/wp-content') ? "wp-content writable\n" : "wp-content NOT writable\n";
На стенді з однаковими правами (каталоги 755, файли 644, власник користувач сайту) отримали таке:
| Що перевіряли | PHP від власника | PHP від www-data |
|---|---|---|
| Запис у wp-content і uploads | так | ні |
| Метод запису файлів WordPress | direct | ftpext: WordPress просить дані FTP |
| Завантаження в медіатеку | працює, файл 644 | «Unable to create directory wp-content/uploads/2026/12» |
| Встановлення плагіна | «Plugin installed successfully.» | «Could not create directory.» |
| PHP-файл з правами 600 | 200 | 403 «Access denied.» |
| wp-config.php з правами 600 | сайт працює | 500, порожня сторінка |
Висновок простий: коли PHP працює від власника, WordPress пише у свої каталоги без жодних 777, і пари 755 та 644 цілком достатньо. Зворотний бік теж варто знати: шкідливий скрипт, якщо потрапить на сайт, отримає права власника. Тому важливіше не розширювати права, а не дати такому скрипту виконатися.

Що віддає вебсервер: chmod 600 на картинці і на PHP-файлі
nginx і Apache працюють від www-data. Статичний файл вони читають самі, а PHP-файл передають у PHP-FPM, який відкриває його від свого користувача. Звідси різниця, яку легко прийняти за дивну поведінку:
| Права файлу | Картинка через Apache | Картинка через nginx | PHP-файл, PHP від власника | PHP-файл, PHP від www-data |
|---|---|---|---|---|
| 644 | 200 | 200 | 200 | 200 |
| 600, 640 або 400 | 403 | 403 | 200 | 403 |
| 000 | 403 | 403 | 403 | 403 |
У лозі Apache така картинка залишає рядок AH00132: file permissions deny server access, у лозі nginx open() ... failed (13: Permission denied), а PHP-FPM пише Unable to open primary script ... (Permission denied). Якщо файлу справді потрібні 640, а вебсервер має його читати, групою файлу має бути www-data: так картинка віддавалась з кодом 200. Інші причини цього коду ми розібрали в статті про помилку 403 Forbidden. Якщо після перенесення сайту зникли лише картинки, а сторінки відкриваються, перевірте права у wp-content/uploads: архіватор або клієнт FTP міг зберегти файли з правами 600.
Чому chmod 777 небезпечний: три перевірки на стенді
777 дозволяє будь-якому процесу і будь-якому користувачу сервера створювати, видаляти і підміняти файли. На стенді це виглядало так:
- Чужий файл виконується від вашого імені. Інший користувач сервера поклав PHP-файл у wp-content з правами 777. Ми відкрили його в браузері, і скрипт працював від імені власника сайту: читав wp-config.php і мав право запису в index.php. З правами 755 той самий користувач отримав «Permission denied».
- Захист можна просто прибрати. Заборона виконувати PHP в uploads лежала у файлі .htaccess з правами 644. Але каталог мав 777, тож сторонній користувач перейменував .htaccess, і тестовий веб-шел знову відповідав кодом 200. Права самого файлу не допомогли, бо видалення і перейменування контролює каталог.
- 777 відчиняє двері вразливому завантажувачу. Ми навмисно поставили скрипт завантаження без перевірки розширень. Коли PHP працював від www-data, а uploads мав 755, файл shell.php не зберігся:
move_uploaded_file(): Unable to move. Після chmod 777 він зберігся і виконався.
Ще два побічні ефекти. WordPress визначає права нових файлів медіатеки за правами каталогу, тому в каталозі 777 завантажені файли отримали 666, тобто стали доступними для запису всім. А файли, які створив www-data, власник сайту вже не змінить: chmod і chown відповіли «Operation not permitted», і виправити таке може лише адміністратор сервера. На хостингу, де акаунти ізольовано, сусіди зазвичай не дістануться до ваших каталогів, але 777 знімає останню лінію захисту.
Як заборонити виконання PHP в uploads
Ця заборона корисна за будь-яких прав: навіть якщо шкідливий файл потрапить в uploads, сервер його не виконає. Для Apache, а також для схеми nginx перед Apache покладіть у wp-content/uploads файл .htaccess:
<FilesMatch "\.(php|phtml|phar)$"> Require all denied </FilesMatch>
Для nginx без Apache додайте в блок server вище за location для PHP, бо регулярні location перевіряються по черзі:
location ~* ^/wp-content/uploads/.*\.(php|phtml|phar)$ {
deny all;
}
На стенді обидва правила дали 403 на shell.php, а картинки з того ж каталогу віддавались з кодом 200. Більше готових правил є в матеріалі про файл .htaccess.
wp-config.php: 600, 640 чи 400
У wp-config.php лежить пароль до бази даних, тож головне питання в тому, хто ще може його прочитати. З правами 644 інший користувач сервера на стенді прочитав рядок з DB_PASSWORD без жодних перешкод.
| Права і група | PHP від власника | PHP від www-data | Інший користувач читає |
|---|---|---|---|
| 644 | працює | працює | так |
| 600 | працює | 500, порожня сторінка | ні |
| 640, група користувача | працює | 500 | ні |
| 400 | працює, але PHP не змінить файл | 500 | ні |
| 440 або 640, група www-data | працює | працює | ні |
Документація WordPress радить 440 або 400 (розділ File Permissions, перевірено 10.11.2026). Якщо PHP працює від вашого користувача, ставте 600: сайт працює, а сусіди файл не прочитають. 400 додатково забороняє змінювати файл скриптам, але деякі плагіни кешування і безпеки самі дописують константи у wp-config.php і тоді повідомлять про помилку. Якщо PHP працює від www-data, підійде 640 або 440 з групою www-data. Без root призначити файлу групу, до якої ви не входите, не вийде, тож тут допоможе підтримка. З правами 600 без такої групи сайт віддав 500 з порожньою сторінкою, а лог PHP показав Failed to open stream: Permission denied in .../wp-load.php. Як розбирати такі відповіді, описано в статті про помилку 500 на хостингу.
umask: чому нові файли отримують 644
Права нового файлу визначає маска umask: вона забирає біти з базових 666 для файлів і 777 для каталогів. На стенді:
| umask | Новий файл | Новий каталог |
|---|---|---|
| 022 | 644 | 755 |
| 002 | 664 | 775 |
| 027 | 640 | 750 |
| 077 | 600 | 700 |
PHP-FPM успадковує umask від процесу, який його запустив. Коли ми запустили пул з umask 002, файли, створені функцією file_put_contents, отримали 664, а каталоги 775. Медіатека WordPress поводилась інакше: завантажені файли все одно мали 644, бо WordPress копіює права з батьківського каталогу і прибирає біт виконання. Саме тому одна помилка з 777 на uploads тягне за собою 666 на кожному новому файлі. Свою маску в SSH показує команда umask, а umask 022 встановлює звичне значення до кінця сесії.
«Could not create directory» у WordPress: перевірте власника
Повідомлення «Could not create directory» під час встановлення плагіна чи оновлення і «Unable to create directory wp-content/uploads/… Is its parent directory writable by the server?» під час завантаження медіа майже завжди означають неправильного власника, а не замалі права. На стенді ми зробили власником wp-content користувача root, як буває після розпакування архіву від імені root. PHP від власника сайту одразу отримав обидві помилки, а WordPress почав просити дані FTP. Після команди (user тут означає ім’я власника сайту)
chown -R user:user wp-content
завантаження і встановлення плагіна знову запрацювали, хоча жодних прав ми не змінювали. Якщо ставите WordPress вручну, розпаковуйте архів від імені свого користувача; покроково процес описано в інструкції як встановити WordPress на хостинг.
Як виправити права масово: команди find
Підключіться до хостингу по SSH, перейдіть у кореневу папку сайту і виконайте:
find . -type d -exec chmod 755 {} +
find . -type f -exec chmod 644 {} +
chmod 600 wp-config.php
Ми заміряли три способи на дереві WordPress з 2777 файлів і 284 каталогів, щоразу попередньо ставлячи всьому 777. Кожен варіант запускали тричі від імені власника сайту:
| Команда | Час на стенді | Результат |
|---|---|---|
find ... -exec chmod ... {} \; |
3,4-3,8 с | 755 і 644, але окремий процес chmod на кожен файл |
find ... -exec chmod ... {} + |
0,03-0,04 с | 755 і 644 |
chmod -R u=rwX,go=rX . |
0,01-0,02 с | файли лишились 755: велика X зберігає виконання там, де воно вже було |
На великому сайті різниця в сотню разів відчутна, тож використовуйте варіант з плюсом. Знайти проблемні файли допоможуть такі команди:
find . -perm -o+w # writable by anyone find . -type f -perm /111 # files with the execute bit find . ! -user $(whoami) -ls # files owned by another user
Якщо остання команда знаходить файли www-data або root, chmod на них не подіє: на стенді масове виправлення зупинилось на файлі www-data з помилкою «Operation not permitted». Без SSH права змінюють у файловому менеджері панелі або в FileZilla: пункт File permissions у контекстному меню дозволяє застосувати значення рекурсивно, окремо до каталогів і окремо до файлів.
chown: хто може змінити власника
Змінити власника файлу може лише root. На стенді користувач сайту на спробу передати файл іншому користувачу отримав «Operation not permitted». На віртуальному хостингу доступу root у вас немає, тому файли з чужим власником виправляє підтримка або відповідна функція панелі. На хостингу для WordPress від RichHost сайтами керують через власну панель керування з ШІ-помічником, а підтримка працює з 10:00 до 20:00 за Києвом і відповідає приблизно за 30 хвилин.
Часті питання
Які права ставити для WordPress?
Каталоги 755, файли 644, wp-config.php 600. Якщо PHP працює від www-data, для wp-config.php потрібні 640 або 440 з групою www-data. Власником усіх файлів має бути ваш користувач.
Чому після chmod 600 не відкривається картинка, а сторінка працює?
Картинку читає вебсервер від www-data, для нього файл з правами 600 закритий, тому він відповідає 403. PHP-файл відкриває PHP-FPM від імені власника, і йому 600 достатньо.
Чи потрібні PHP-файлам права 755?
Ні. Інтерпретатор лише читає PHP-скрипт, біт виконання йому не потрібен. 755 потрібне каталогам і shell-скриптам, які ви запускаєте вручну або через cron.
WordPress просить дані FTP під час встановлення плагіна. Що не так?
PHP не може писати у файли сайту, бо працює від іншого користувача або файли мають чужого власника. На стенді обидва випадки давали саме цей запит. Виправте власника, а не ставте 777.
Чи безпечні права 775 і 664?
Вони дають право запису групі. Якщо в групі лише ваш користувач, ризик невеликий, але й користі немає: коли PHP працює від власника, групове право запису не потрібне. Краще залишити 755 і 644.



