ZIM-НИЙ SAAALEЗимние скидки: до −50% на старт и −20% на продление
до 31.01.2026 Подробнее
Выберите продукт

Apache 403 Forbidden: права, Require, DocumentRoot, suEXEC и SELinux — практическая диагностика

403 Forbidden в Apache почти всегда означает явный запрет: правило Require/Directory, несоответствие DocumentRoot/Alias, права на путь, ограничения suEXEC или блокировка SELinux. Ниже — пошаговая диагностика по логам и командам.
Apache 403 Forbidden: права, Require, DocumentRoot, suEXEC и SELinux — практическая диагностика

Что означает 403 в Apache и почему это почти всегда «настройка доступа»

Сообщение 403 Forbidden (часто как «You don't have permission to access / on this server») означает: Apache запрос получил, но сознательно отказал в доступе. Это принципиально отличается от 404: при 404 ресурса/маршрута нет, при 403 он есть, но для него не выполняются правила доступа или ограничения безопасности.

Практически все причины apache 403 укладываются в четыре группы:

  • директивы авторизации/доступа Apache 2.4: Require и контейнеры <Directory>, <Location>, <Files> (включая наследование и переопределения);
  • права файловой системы: владелец/группа, режимы, и особенно «x» на каталогах по всей цепочке;
  • надстройки запуска: suexec и требования к владельцу/правам для CGI/скриптов;
  • MAC-политики: SELinux для httpd (реже AppArmor).

Дальше — порядок проверки, который обычно дает причину 403 за 10–15 минут.

Шаг 1. Сразу смотрим логи: там обычно написана причина

При 403 лучше не «гадать по конфигу». В error log почти всегда есть формулировка, которая указывает, это правило Require, права/контекст или suEXEC. На SELinux-системах дополнительно полезен audit log.

Где искать error log

Пути зависят от дистрибутива и настроек vhost. Частые варианты:

  • Debian/Ubuntu: /var/log/apache2/error.log
  • RHEL/Alma/Rocky/CentOS: /var/log/httpd/error_log
  • ошибки конкретного сайта могут быть в отдельном файле из ErrorLog внутри VirtualHost.
sudo tail -n 200 /var/log/apache2/error.log
sudo tail -n 200 /var/log/httpd/error_log

Типовые строки, которые прямо указывают на причину:

  • client denied by server configuration или AH01630: client denied by server configuration — запрет на уровне Require/<Directory>/.htaccess;
  • AH00036: access to ... denied (filesystem path ...) — правила <Directory> не покрывают реальный путь или конфликтуют;
  • Permission denied при попытке открыть файл/каталог — чаще всего права на ФС или SELinux;
  • упоминания suexec — отказ запуска CGI/скрипта из-за требований suEXEC.

Шаг 2. Apache 2.4: Require/Directory и «Require all granted»

В Apache 2.4 доступ управляется директивой Require. Самый частый сценарий после переноса конфигов (или при сборке нового vhost): админ ожидает «по умолчанию разрешено», а фактически нет явного разрешающего правила на нужный каталог.

Если в error log есть «client denied by server configuration», почти всегда причина в блоках <Directory> или .htaccess: отсутствует Require all granted, либо выше по дереву есть более строгий запрет, который выигрывает по приоритету.

Разрешение доступа к DocumentRoot: проверьте совпадение путей

Apache принимает решение на основании наиболее подходящих блоков <Directory>.htaccess, если разрешено через AllowOverride). Типичная ошибка: vhost указывает один DocumentRoot, а правила <Directory> описывают другой путь или не описывают вовсе.

Убедитесь, что для реального DocumentRoot есть явный блок с разрешением:

<VirtualHost *:80>
  ServerName example.com
  DocumentRoot /var/www/example/public

  <Directory /var/www/example/public>
    Require all granted
    Options FollowSymLinks
    AllowOverride All
  </Directory>
</VirtualHost>

Ключевой момент: Require all granted должен применяться к тому каталогу, из которого реально отдаются файлы.

Частые ловушки в Directory/Require

  • Запрет стоит выше: общий блок для /var/www с Require all denied перекрывает частный (или подключается конфиг с более высоким приоритетом).
  • Неправильный контейнер: <Location> работает с URL, а <Directory> — с путями ФС. Для DocumentRoot почти всегда нужен <Directory>.
  • Симлинки: при раздаче через symlink запрет может прилететь из Options -FollowSymLinks или требования SymLinksIfOwnerMatch.
  • Нет «x» на родительских каталогах: даже при Require all granted Apache не «пройдет» по пути без execute на директориях (см. следующий шаг).

Пример конфигурации Apache с Directory и Require all granted

Шаг 3. Права на файлы и каталоги: диагностика по всей цепочке пути

Когда Apache пишет «Permission denied», это не всегда про Require. Очень часто forbidden apache связан с DAC-правами на уровне ОС: неверный владелец, слишком строгий режим, или отсутствует execute-бит на одном из каталогов по пути.

Лучшая команда для 403 из-за прав

namei -l /var/www/example/public/index.php

namei -l показывает права на каждый каталог в цепочке. Ищите место, где пользователь/группа Apache «упирается» (обычно нет «x»).

Отправная точка, которая обычно работает для статики:

  • каталоги: 755 (всем «x», чтобы можно было «проходить» по пути);
  • файлы: 644 (читать можно, писать нет).

Это не универсальное правило, но полезный базовый ориентир для диагностики.

Под каким пользователем работает Apache

ps -eo user,group,comm | grep -E 'apache2|httpd' | head

Также можно посмотреть директивы User и Group в конфиге Apache (расположение зависит от дистрибутива).

Почему chmod -R 777 не лечит 403

Попытка «вылечить» 403 правами 777 обычно делает только хуже:

  • резко увеличивает поверхность атаки (любой локальный пользователь/процесс может писать в код/конфиги);
  • не помогает при SELinux (MAC важнее DAC);
  • может ломать ограничения suEXEC, где критичны владельцы и «неопасные» режимы.

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

Виртуальный хостинг FastFox
Виртуальный хостинг для сайтов
Универсальное решение для создания и размещения сайтов любой сложности в Интернете от 95₽ / мес

Шаг 4. DocumentRoot, Alias и «не тот каталог»: когда конфиг выглядит правильно

Иногда вы правите «правильный» DocumentRoot, но запрос фактически уходит в другой путь из-за Alias, ScriptAlias, дополнительного vhost или включенного набора конфигов. В итоге правило/права исправлены «не там», и 403 остается.

Что проверить в первую очередь:

  • есть ли в конфиге Alias/ScriptAlias для нужного URI;
  • не подключен ли другой конфиг в conf.d/sites-enabled, который переопределяет доступ;
  • не перепутан ли каталог публикации (public, www, htdocs).

Самая полезная команда при множестве include — «карта» активной конфигурации:

apachectl -S

Она показывает, какой vhost обслуживает запрос и из какого файла он загружен. После этого обычно становится ясно, почему «вроде все настроено, но не работает».

Если вы параллельно приводите в порядок заголовки безопасности и хотите понять, какие заголовки реально отдаются на ответах, пригодится отдельный разбор: как настроить HTTP security headers в Nginx и Apache.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Шаг 5. suEXEC: 403 из-за владельцев и «небезопасных» прав

Если включен suexec (или схожий механизм), 403 может быть не про Require, а про то, что Apache отказывается запускать CGI/скрипты из-за несоответствия требованиям: владелец, права, расположение каталога вне разрешенного дерева и т.д.

Как понять, что виноват suEXEC

Частые признаки:

  • 403 возникает только на CGI/скрипте, а статика отдается;
  • в error log появляются строки с suexec или отказ запуска;
  • на RHEL-подобных системах может быть отдельный лог suEXEC.

Проверьте модуль:

apachectl -M | grep -i suexec

И посмотрите ограничения suEXEC (важны DOC_ROOT и прочие параметры):

sudo suexec -V

Если ваш DocumentRoot находится вне DOC_ROOT, suEXEC может законно отказать.

Частые причины отказа suEXEC

  • скрипт/каталог имеет «опасные» права (например, доступ на запись для группы/всех там, где suEXEC ожидает жестче);
  • владелец файла/каталога не совпадает с ожидаемым;
  • скрипт запускается из каталога вне разрешенного дерева.

Шаг 6. SELinux: права в Linux правильные, но Apache все равно возвращает 403

На RHEL/Alma/Rocky/CentOS при включенном SELinux в режиме Enforcing одних UNIX-прав может быть недостаточно. Процессу Apache может быть запрещено читать файлы из-за контекста безопасности. Снаружи это выглядит как «обычный 403» или как Permission denied в логах.

Быстрая проверка режима SELinux

getenforce
sestatus

Если видите Enforcing, SELinux участвует в решении.

Смотрим, что именно блокируется

Самый полезный источник — audit log с AVC событиями:

sudo tail -n 200 /var/log/audit/audit.log

Если установлены утилиты, удобно быстро отфильтровать по httpd:

sudo ausearch -m avc -ts recent | grep -i httpd | tail -n 50

Исправление: правильный контекст на DocumentRoot

Для статической отдачи контент обычно должен иметь тип вроде httpd_sys_content_t. Посмотрите текущие контексты:

ls -laZ /var/www/example/public | head

Если контекст «не вебовый» (часто после rsync из домашней директории или деплоя в нестандартный путь), Apache будет получать запрет.

Типовой подход: назначить правильный контекст и закрепить его правилом:

sudo semanage fcontext -a -t httpd_sys_content_t '/var/www/example/public(/.*)?'
sudo restorecon -Rv /var/www/example/public

Если приложению нужно писать (uploads, cache), делайте это в отдельном каталоге и назначайте права и контексты именно для него. Не превращайте весь проект в «writeable» — это обычно и небезопасно, и сложно поддерживать.

Поиск SELinux AVC блокировок для httpd в audit.log

Шаг 7. Быстрый чек-лист: диагностика за 10 минут

  1. Откройте error log и найдите точную строку отказа (особенно «client denied by server configuration»).
  2. Проверьте, какой vhost обслуживает запрос: apachectl -S.
  3. Убедитесь, что для DocumentRoot есть <Directory ...> с Require all granted (Apache 2.4).
  4. Проверьте права по всей цепочке: namei -l /path/to/file.
  5. На RHEL-подобных: getenforce, затем audit.log на AVC и при необходимости restorecon и semanage fcontext.
  6. Если 403 на CGI: проверьте suexec -V и сообщения suEXEC в логах.

Типовые сценарии и решения

Сценарий A: «Включил новый vhost, вижу 403 на /»

Чаще всего отсутствует разрешение в <Directory> для нового DocumentRoot. Добавьте блок, проверьте конфигурацию и перезагрузите Apache.

sudo apachectl configtest
sudo systemctl reload apache2
sudo systemctl reload httpd

Сценарий B: «Все права 755/644, но все равно 403 на Alma/Rocky»

С высокой вероятностью это SELinux и неверный контекст на файлах. Проверьте ls -Z, примените restorecon, а для нестандартного пути добавьте правило semanage fcontext.

Сценарий C: «403 только на uploads или cache»

Это уже не чтение, а запись. Нужны корректные права на запись и корректный SELinux-контекст для каталога записи. Не делайте весь проект записываемым — вынесите запись в отдельные директории.

Сценарий D: «403 при раздаче через симлинк»

Проверьте:

  • включен ли Options FollowSymLinks (или соблюдены условия SymLinksIfOwnerMatch) в нужном <Directory>;
  • права и владельцев целевого каталога симлинка;
  • SELinux-контекст целевого пути (если применимо).

Как меньше ловить 403 при деплое: практики из админки

  • Единый стандарт путей: держите сайты в предсказуемых каталогах, чтобы реже упираться в suEXEC/SELinux.
  • Разделяйте код и запись: код и статика должны быть read-only, запись — только в выделенные каталоги (uploads/cache/tmp).
  • Проверяйте конфиг перед reload: apachectl configtest в CI или в деплой-скрипте.
  • После миграций на RHEL-подобных: не забывайте про restorecon на дерево сайта.

Если вы выбираете, на чем размещать проекты и как проще разруливать права/владельцев на нескольких сайтах, удобно разводить их по отдельным инстансам на VDS: меньше сюрпризов с окружением и проще диагностика 403 по «чистым» логам.

Вывод

403 Forbidden в Apache — это не «мистика», а конкретный запрет: либо правила доступа (Require/<Directory>), либо права ФС, либо ограничения suexec, либо SELinux для httpd. Самый быстрый путь к решению: начать с error log, затем проверить, какой vhost обслуживает запрос, и пройтись по цепочке доступа от конфигурации до контекста SELinux.

Когда диагностика выстроена по шагам, forbidden apache перестает быть черным ящиком и превращается в рутинную задачу.

Поделиться статьей

Вам будет интересно

Grafana Tempo + Loki + Prometheus: корреляция traceID и быстрый triage инцидентов OpenAI Статья написана AI (GPT 5)

Grafana Tempo + Loki + Prometheus: корреляция traceID и быстрый triage инцидентов

Пошагово связываем Grafana Tempo, Loki и Prometheus в единую observability-схему: OpenTelemetry-трейсы, логи с traceID и метрики. ...
Kubernetes DNS: таймауты, MTU и conntrack — диагностика через CoreDNS, tcpdump и PMTUD OpenAI Статья написана AI (GPT 5)

Kubernetes DNS: таймауты, MTU и conntrack — диагностика через CoreDNS, tcpdump и PMTUD

Если в Kubernetes периодически не резолвится DNS или внешние API отвечают timeout, причина часто в MTU/PMTUD, conntrack и настройк ...
Kubernetes CrashLoopBackOff: события, пробы, exit codes и backoff — практический разбор OpenAI Статья написана AI (GPT 5)

Kubernetes CrashLoopBackOff: события, пробы, exit codes и backoff — практический разбор

CrashLoopBackOff в Kubernetes — не «ошибка», а симптом: контейнер быстро завершается, kubelet перезапускает его и увеличивает пауз ...