# Apache httpd - веб-сервер _Протоколы · LinuxLab Knowledge Base_ **TL;DR:** Apache httpd - веб-сервер. На RHEL пакет `httpd`, конфиг `/etc/httpd/conf/httpd.conf`. На Debian/Ubuntu пакет `apache2`, конфиг `/etc/apache2/apache2.conf` + `sites-enabled/`. ## Apache vs nginx - когда что В современном Linux два мейнстрим веб-сервера: - **Apache** - process-per-request (worker/event MPM), модульный, `.htaccess`, PHP через mod_php. Стандарт для shared hosting, LAMP-стека, легаси. - **nginx** - event-driven, легче на ресурсах, проще конфиг, лучше для static + reverse proxy. Apache всё ещё имеет смысл когда: - Нужны `.htaccess`-овые правки силами user'ов без рестарта. - mod_*-экосистема (mod_wsgi, mod_authnz_ldap, mod_security). - Готовый продукт ожидает Apache (ZendServer, cPanel, mailman). В остальных случаях - nginx или Caddy. ## Установка - пакетные различия | Дистрибутив | Пакет | Демон | Конфиг | run-as | |-----------------|-----------|----------------|------------------------------------------------|----------| | RHEL/Fedora | `httpd` | `httpd` | `/etc/httpd/conf/httpd.conf` + `conf.d/` | `apache` | | Debian/Ubuntu | `apache2` | `apache2` | `/etc/apache2/apache2.conf` + `sites-enabled/` | `www-data` | ```bash # RHEL sudo dnf install httpd sudo systemctl enable --now httpd # Debian sudo apt install apache2 sudo systemctl enable --now apache2 ``` Дальше `httpd` для краткости, на Debian замени на `apache2`. ## Структура каталогов на Debian (модель «sites-available») ``` /etc/apache2/ ├── apache2.conf ← главный, читает все остальные ├── ports.conf ← Listen 80, 443 ├── conf-available/ ← фрагменты ├── conf-enabled/ ← симлинки на активные ├── mods-available/ ← все модули (.load + .conf) ├── mods-enabled/ ← симлинки на активные модули ├── sites-available/ ← конфиги virtual host'ов │ ├── 000-default.conf │ └── example.org.conf └── sites-enabled/ ← симлинки на активные └── example.org.conf -> ../sites-available/example.org.conf ``` Активация через утилиты: ```bash sudo a2ensite example.org # symlink в sites-enabled sudo a2dissite example.org # снять sudo a2enmod ssl rewrite # включить модули sudo a2dismod autoindex sudo systemctl reload apache2 ``` RHEL такого разделения **нет** - все конфиги дропаются в `/etc/httpd/conf.d/*.conf`, модули загружаются через `LoadModule` в `/etc/httpd/conf.modules.d/*.conf`. ## Process model - почему root и www-data одновременно Apache **стартует от root** чтобы открыть [[capabilities|порты <1024]] (80, 443 требуют CAP_NET_BIND_SERVICE), потом **fork'ает worker'ов как unprivileged user** (`www-data` или `apache`). ```bash ps -ef | grep httpd # root 1234 1 0 /usr/sbin/httpd -DFOREGROUND ← parent (master) # apache 1235 1234 0 /usr/sbin/httpd -DFOREGROUND ← worker # apache 1236 1234 0 /usr/sbin/httpd -DFOREGROUND ← worker ``` Worker'ы обрабатывают запросы. Если в них уязвимость - exploit имеет только права `apache`, не root. Поэтому `/var/www/html/` должна быть читаемая `apache`, но не writable (иначе RCE → запись на диск). ## VirtualHost - несколько сайтов на одном IP Один хост может обслуживать несколько доменов на одном IP по `Host:` заголовку из HTTP/1.1. ```apache # /etc/apache2/sites-available/example.org.conf ServerName example.org ServerAlias www.example.org DocumentRoot /var/www/example.org ErrorLog ${APACHE_LOG_DIR}/example.org-error.log CustomLog ${APACHE_LOG_DIR}/example.org-access.log combined Options -Indexes +FollowSymLinks AllowOverride All # разрешить .htaccess Require all granted ``` Подвохи: - **Первый VirtualHost = default**: запросы с неизвестным `Host:` падают в него. Часто хочется default-конфиг с 444 ответом для защиты от «спам-запросов на IP». - **`*:80` vs `IP:80`** - `*` ловит все интерфейсы; явный IP - только этот. - **`` vs `` vs ``** - каталог на диске vs URL-путь vs паттерн файла. Путать опасно: правила контроля доступа могут не сработать. ## HTTPS - mod_ssl + Let's Encrypt ```bash # 1. Включить модуль sudo a2enmod ssl sudo systemctl reload apache2 # 2. Получить сертификат (certbot пропишет конфиг сам) sudo apt install certbot python3-certbot-apache sudo certbot --apache -d example.org -d www.example.org # certbot создаст: # /etc/apache2/sites-available/example.org-le-ssl.conf ``` Минимальный SSL-VirtualHost вручную: ```apache ServerName example.org DocumentRoot /var/www/example.org SSLEngine on SSLCertificateFile /etc/letsencrypt/live/example.org/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/example.org/privkey.pem # Современные шифры SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1 SSLCipherSuite HIGH:!aNULL:!MD5 SSLHonorCipherOrder on ``` Про сам [tls-handshake](/kb/tls-handshake.md) - отдельная статья. ## Reverse proxy для backend-приложения ```apache ServerName api.example.org ProxyPreserveHost On ProxyPass / http://127.0.0.1:8000/ ProxyPassReverse / http://127.0.0.1:8000/ RequestHeader set X-Forwarded-Proto "http" ``` Нужны модули `proxy` и `proxy_http`: ```bash sudo a2enmod proxy proxy_http ``` Backend (uvicorn/gunicorn/etc.) слушает loopback:8000, Apache на 80/443 отдаёт TLS, заголовки и rate-limit'ы. ## .htaccess - правила per-каталог без перезагрузки Основная фича Apache - файл `.htaccess` в любом каталоге может содержать директивы конфига и применяется БЕЗ рестарта сервера. Удобно для shared hosting'а где user-у дают только FTP-доступ. ```apache # /var/www/example.org/.htaccess Options -Indexes ErrorDocument 404 /404.html RewriteEngine On RewriteRule ^old-page$ /new-page [R=301,L] ``` Чтобы это работало - в VirtualHost должно стоять `AllowOverride All` для каталога. По умолчанию - `None` (.htaccess игнорируется). Цена: Apache **читает .htaccess на каждый запрос** в этой иерархии. На high-load - выключай и переноси правила в основной конфиг. ## Управление ```bash sudo systemctl reload httpd # перечитать конфиг без обрыва соединений sudo systemctl restart httpd # полный рестарт sudo apachectl configtest # проверка синтаксиса (== httpd -t) sudo apachectl -S # показать все VirtualHost'ы и их правила sudo apachectl -M # список загруженных модулей ``` **Всегда** `configtest` перед `reload`. Иначе syntax error → демон не перезапустится, и сайт ляжет. ## Логи RHEL: `/var/log/httpd/{access,error}_log`. Debian: `/var/log/apache2/{access,error}.log`. ```bash sudo tail -f /var/log/apache2/error.log # ошибки в реалтайме sudo tail -f /var/log/apache2/access.log # запросы ``` Формат `combined` (default): ``` 192.168.0.5 - - [29/Apr/2026:14:23:11 +0300] "GET / HTTP/1.1" 200 1234 "-" "Mozilla/5.0..." ↑ ↑ ↑ ↑ client request code size ``` Logrotate конфиг обычно `/etc/logrotate.d/httpd` ротирует daily/weekly. ## Безопасность - обязательный минимум 1. **Не запускать как root postfork**: убедись `User apache` / `User www-data` стоит в конфиге. 2. **Скрыть версию**: `ServerTokens Prod` + `ServerSignature Off` в `apache2.conf`. 3. **Отключить листинг каталогов**: `Options -Indexes` для всех ``. 4. **Запретить .git/.env**: `` + `Require all denied`. 5. **HSTS**: `Header always set Strict-Transport-Security "max-age=63072000"`. 6. **[fail2ban](/kb/fail2ban.md)** на лог error.log - банить тех кто долбит 404 и 401. 7. **mod_security** + OWASP ruleset - WAF для типичных атак. ## Дебаг - типичные проблемы ```bash # 1. Запущен? systemctl status httpd ss -tlnp 'sport = :80' # слушает порт? # 2. Куда идут логи в реалтайме sudo tail -F /var/log/httpd/error_log # 3. Какой VirtualHost матчится для имени sudo apachectl -S | grep example.org # 4. Простой curl-тест curl -I http://localhost curl -kvI https://example.org ``` Частые ошибки: - **403 Forbidden** на чистом сайте → SELinux на RHEL. Проверить `ls -Z /var/www/html` - нужен контекст `httpd_sys_content_t`. `sudo restorecon -R /var/www/html`. - **Permission denied** в логе → `apache`/`www-data` не может прочитать DocumentRoot. `chmod o+rX -R` или нужный ACL. - **Address already in use** при старте → кто-то другой уже на 80 (`ss -tlnp 'sport = :80'` найдёт). ## Команды ```bash sudo apachectl configtest ``` Проверка синтаксиса конфига перед reload - обязательно, иначе сайт упадёт ```bash sudo apachectl -S ``` Показать все VirtualHost'ы и какой выбран по умолчанию - диагностика matching'а ```bash sudo a2ensite example.org && sudo systemctl reload apache2 ``` Активировать VirtualHost из sites-available на Debian - symlink + reload ```bash sudo certbot --apache -d example.org ``` Получить Let's Encrypt сертификат и автоматически настроить SSL-VirtualHost ```bash sudo tail -F /var/log/apache2/error.log ``` Реалтайм лог ошибок - главный инструмент дебага 500/403/permissions ## См. также - [TLS handshake](/kb/tls-handshake.md) - [HTTP/1.1, HTTP/2, HTTP/3](/kb/http-protocol.md) - [curl - HTTP-клиент из терминала](/kb/cmd-curl.md) - [fail2ban - автобан по логам](/kb/fail2ban.md) - [systemd - init и менеджер сервисов](/kb/systemd.md)