Apache HTTP Server: история и принцип работы веб-сервера

Apache HTTP Server: история и принцип работы веб-сервера Полезное

Apache HTTP Server (в быту «Апач», бинарь httpd или apache2) — это свободный веб-сервер: он принимает HTTP- и HTTPS-запросы и отдает ответ — либо файл с диска, либо результат приложения (PHP, Python и т.п.), которому передает запрос. Материал опирается на ветку 2.4.x — актуальную стабильную на сентябрь 2026 года. Ниже — история, путь запроса, модели MPM, модули и .htaccess, базовая безопасная настройка (на примере Debian/Ubuntu) и сравнение с nginx.

Три слова, которые часто путают:

Термин Что это
Apache Software Foundation (ASF) некоммерческий фонд, под которым живут сотни проектов (Tomcat, Kafka и др.)
Apache HTTP Server конкретный продукт фонда — веб-сервер, о нем эта статья
httpd / apache2 имя бинаря и пакета: httpd в RHEL/Fedora, apache2 в Debian/Ubuntu

Краткая история Apache

В начале 1990-х было два заметных веб-сервера: CERN httpd (его делали в ЦЕРН) и NCSA HTTPd (Национальный центр суперкомпьютерных приложений, США). Это разные проекты разных организаций. После 1994 года развитие NCSA HTTPd замедлилось, и администраторы сайтов стали обмениваться собственными исправлениями — патчами.

В 1995 году группа таких администраторов (Apache Group) собрала патчи к NCSA HTTPd в общий сервер. Популярная расшифровка названия — «a patchy server», «сервер из заплаток». Сам проект в FAQ объясняет выбор имени уважением к народу апачей, а расшифровку «a patchy server» называет популярной, но неверной версией, которая просто прижилась.

Год Событие
1995 первые публичные релизы, версия 1.0 — в декабре
1998 ветка 1.3, долго остававшаяся основной
1999 основан фонд Apache Software Foundation
2002 ветка 2.0: MPM, библиотека APR, фильтры ввода-вывода
2005 ветка 2.2
2012 ветка 2.4: стабильный event MPM, новая модель доступа Require

Ветка 2.4 жива до сих пор: выходят корректирующие релизы 2.4.x, в основном с исправлениями безопасности.

Как Apache обрабатывает запрос

Упрощенная модель пути запроса (на деле обработка разбита на фазы-хуки, в которые встраиваются модули):

  1. Процесс или поток, выделенный MPM, принимает соединение; для HTTPS mod_ssl проводит TLS-рукопожатие.
  2. По заголовку Host (и SNI при TLS) выбирается виртуальный хост.
  3. URL сопоставляется с ресурсом: DocumentRoot, Alias, правила mod_rewrite.
  4. Проверяется доступ: директивы Require, аутентификация.
  5. Обработчик формирует ответ: отдает статический файл или проксирует запрос приложению (например, PHP-FPM через mod_proxy_fcgi).
  6. Выходные фильтры обрабатывают ответ (сжатие mod_deflate), запрос пишется в лог.

Две поправки к распространенным мифам. Apache не обрабатывает запросы строго по одному: параллельность обеспечивает MPM. И основной конфиг (httpd.conf, apache2.conf и включенные файлы) читается при старте. После его правки нужен перезапуск или мягкая перезагрузка (graceful). Без перезагрузки на каждый запрос перечитываются только файлы .htaccess.

MPM: prefork, worker и event

MPM (Multi-Processing Module) — модуль, который решает, как Apache распределяет соединения по процессам и потокам. Одновременно активен ровно один MPM.

MPM Как работает Плюсы Когда брать
prefork пул процессов, в каждом один поток изоляция, совместим с не потокобезопасным кодом только для legacy-модулей вроде mod_php
worker несколько процессов, в каждом много потоков меньше памяти на соединение если event недоступен
event как worker, но keep-alive соединения ждет отдельный поток-слушатель потоки не простаивают на «висящих» соединениях выбор по умолчанию для новых установок

В Windows используется свой MPM — mpm_winnt. Какой MPM активен у вас, показывает команда:

apachectl -V | grep -i 'server mpm'

Ожидаемый вывод на типичном сервере Ubuntu:

Server MPM:     event

Типичная ловушка: пакет mod_php в Debian/Ubuntu переключает сервер на prefork, потому что сам модуль рассчитан на процессную модель. Современный вариант — event плюс PHP-FPM через mod_proxy_fcgi.

Лимиты event задаются так (числа учебные, реальные зависят от памяти и нагрузки):

<IfModule mpm_event_module>
    StartServers             2
    ServerLimit              6
    ThreadsPerChild         25
    MaxRequestWorkers      150
</IfModule>

Здесь MaxRequestWorkers не может превышать ServerLimit * ThreadsPerChild: 6 процессов по 25 потоков дают потолок 150 одновременно обслуживаемых запросов. Если задать больше, Apache урежет значение и предупредит об этом.

Модули

Ядро Apache отвечает за разбор конфигурации, соединения и HTTP, а почти вся функциональность — в модулях. Модуль может быть вкомпилирован статически или подгружаться директивой LoadModule (DSO). Список загруженных модулей: apachectl -M.

Модуль Зачем
mod_ssl HTTPS и TLS
mod_rewrite переписывание URL по правилам
mod_proxy, mod_proxy_fcgi обратный прокси, передача запросов в PHP-FPM и приложения
mod_headers управление заголовками, например HSTS
mod_deflate сжатие ответов
mod_autoindex автолистинг каталогов — обычно не нужен в production

Практика простая: включено только то, что используется — лишний модуль означает лишний код с потенциальными уязвимостями. В Debian/Ubuntu для этого есть a2enmod и a2dismod.

Конфигурация: основной файл, виртуальные хосты и .htaccess

Расположение зависит от дистрибутива: /etc/apache2/apache2.conf и каталоги sites-available/, conf-available/ в Debian/Ubuntu; /etc/httpd/conf/httpd.conf и conf.d/ в RHEL-семействе.

Настройки применяются слоями: основной конфиг -> блок <VirtualHost> -> блок <Directory> -> .htaccess. Последний слой работает только в пределах, которые разрешает AllowOverride в конфиге сервера. Поэтому .htaccess не «главнее» httpd.conf — он уточняет настройки своего каталога в рамках разрешенного.

Начиная с 2.3.9 значение AllowOverride по умолчанию — None, и это разумно. При включенном .htaccess Apache на каждый запрос ищет этот файл во всех каталогах по пути к ресурсу. Если у вас есть доступ к основному конфигу, правила лучше держать там.

Базовая безопасная конфигурация

Пример для Debian/Ubuntu. Глобальные директивы в этих системах уже есть в /etc/apache2/conf-available/security.conf (по умолчанию ServerTokens OS и ServerSignature On) — значения правим там. Отдельный файл вроде hardening.conf не сработает: файлы из conf-enabled/ читаются по алфавиту, и более поздний security.conf перезапишет настройку. В security.conf должно получиться:

ServerTokens Prod
ServerSignature Off
TraceEnable Off

Виртуальный хост — в /etc/apache2/sites-available/example.conf:

<VirtualHost *:80>
    ServerName example.com
    Redirect permanent / https://example.com/
</VirtualHost>

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

    SSLEngine on
    SSLCertificateFile    /etc/letsencrypt/live/example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
    SSLProtocol -all +TLSv1.2 +TLSv1.3

    <Directory /var/www/example/public>
        Options -Indexes
        AllowOverride None
        Require all granted
    </Directory>

    Header always set Strict-Transport-Security "max-age=86400"
</VirtualHost>

Что делает каждая часть. ServerTokens Prod оставляет в заголовке Server только слово Apache, без версии и списка модулей. Options -Indexes отключает листинг: если в каталоге нет index.html, сервер вернет 403, а не список файлов. Остальные опции наследуются из родительского блока: в Debian/Ubuntu это Options Indexes FollowSymLinks для /var/www, поэтому FollowSymLinks останется включенным. Отдельно добавлять +FollowSymLinks в «безопасный» шаблон незачем: это не защитная настройка, а разрешение ходить по символическим ссылкам. Нужен он, например, для правил mod_rewrite в контексте каталога. Если приложению ссылки не нужны, их можно выключить через -FollowSymLinks, но и это не надежная граница безопасности: проверка ссылок подвержена гонкам, права на файлы важнее. SSLProtocol оставляет только TLS 1.2 и 1.3 (TLS 1.3 требует Apache 2.4.37+ и OpenSSL 1.1.1 или новее). HSTS начинают с малого max-age и увеличивают, когда HTTPS стабильно работает.

Применять изменения безопасно — по чек-листу, а не одной командой:

  1. Копия конфигурации: sudo cp -a /etc/apache2 /root/apache2-backup-$(date +%F).
  2. Административный доступ сохранен: текущую SSH-сессию не закрывайте, откройте вторую — из нее будете проверять результат.
  3. Проверка синтаксиса и виртуальных хостов:
sudo a2enmod ssl headers
sudo a2ensite example
sudo apache2ctl configtest   # ожидается Syntax OK
sudo apache2ctl -S           # какие VirtualHost активны и какой из них по умолчанию

configtest проверяет только синтаксис. Он не знает, доступно ли приложение, правильный ли DNS, полная ли цепочка сертификата и открыт ли порт. Вывод apache2ctl -S показывает, что example.com попадет в нужный хост, а не в хост по умолчанию.

  1. Перезагрузка: sudo systemctl reload apache2.
  2. Проверка с самого сервера и снаружи. Локально, с правильным Host и SNI, без зависимости от DNS: curl -sI --resolve example.com:443:127.0.0.1 https://example.com/ — в ответе должны быть Server: Apache и Strict-Transport-Security. Затем тот же запрос без --resolve с другой машины.
  3. Откат при ошибке: вернуть каталог из копии, повторить configtest и reload.

Для самопроверки конфигов — учебный скрипт на Python, который ищет три типичные проблемы:

def audit(conf: str) -> list[str]:
    lines = [l.split("#", 1)[0].strip() for l in conf.splitlines()]
    lines = [l for l in lines if l]
    issues = []
    tokens = [l.split()[1] for l in lines if l.lower().startswith("servertokens ")]
    if not tokens or tokens[-1].lower() != "prod":
        issues.append("ServerTokens не Prod: версия видна в заголовке Server")
    for l in lines:
        words = l.split()
        if words[0].lower() == "options" and ("Indexes" in words or "+Indexes" in words):
            issues.append("включен листинг каталогов: " + l)
        if words[0].lower() == "sslprotocol":
            allowed = set()
            for w in words[1:]:
                name = w.lstrip("+-")
                group = {"TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"} if name == "all" else {name}
                allowed = allowed - group if w.startswith("-") else allowed | group
            old = sorted(allowed & {"SSLv3", "TLSv1", "TLSv1.1"})
            if old:
                issues.append("устаревшие протоколы: " + ", ".join(old))
    return issues

bad = """
ServerTokens Full
Options Indexes FollowSymLinks
SSLProtocol all
"""
good = """
ServerTokens Prod
Options -Indexes
SSLProtocol -all +TLSv1.2 +TLSv1.3
"""
for name, conf in (("bad", bad), ("good", good)):
    print(name, audit(conf) or "OK")

Скрипт печатает три замечания для bad и OK для good:

bad ['ServerTokens не Prod: версия видна в заголовке Server', 'включен листинг каталогов: Options Indexes FollowSymLinks', 'устаревшие протоколы: TLSv1, TLSv1.1']
good OK

Граница примера: это учебная проверка трех директив в одном тексте, она не учитывает Include, контекст блоков и значения по умолчанию. Она не заменяет configtest и специализированные TLS-сканеры.

Что еще нужно в production

Конфиг выше — базовый, а не «полностью защищенный»: ServerTokens Prod лишь скрывает версию и не закрывает уязвимости. Дополнительно нужны регулярные обновления apache2/httpd и OpenSSL, автопродление сертификата, лимиты Timeout и LimitRequestBody под приложение, доступ к mod_status только с доверенных адресов, журналы с ротацией и мониторингом.

Фаервол: наружу открывайте только нужные сервисы (для веб-сервера — 80 и 443), но до включения правил разрешите административный канал — SSH или VPN, лучше только с доверенных адресов. Иначе фаервол оборвет текущую сессию и оставит сервер без удаленного управления. Держите вторую SSH-сессию открытой и заранее подготовьте откат правил.

Рабочие процессы должны идти от непривилегированного пользователя — от root стартует только главный процесс, чтобы занять порт 80. В Debian/Ubuntu это обычно www-data, в RHEL-семействе — apache. Проверить можно директивами User/Group в конфиге и списком процессов: ps -o user,cmd -C apache2 (в RHEL — -C httpd).

Apache и nginx: что выбрать

Критерий Apache HTTP Server nginx
Модель MPM: процессы и/или потоки событийная, несколько процессов-воркеров
Статика при большом числе соединений хорошо с event обычно экономнее по памяти
Настройка на уровне каталога .htaccess без перезагрузки нет аналога, только основной конфиг
Типичная роль shared-хостинг, legacy-приложения, сложные правила доступа обратный прокси, балансировщик, отдача статики

Частая схема — nginx на входе отдает статику, Apache за ним обслуживает приложение. Для нового проекта без .htaccess и legacy-модулей выбор чаще определяется опытом команды.

Если не получилось

  • AH00558: Could not reliably determine the server’s fully qualified domain name — не задан ServerName глобально; предупреждение, а не ошибка.
  • Address already in use на порту 80 — порт занят другим сервером, например nginx; посмотрите ss -ltnp.
  • 403 Forbidden — нет индексного файла при -Indexes, не хватает Require all granted или прав на каталог у пользователя воркеров (www-data в Debian/Ubuntu, apache в RHEL).
  • .htaccess игнорируется — AllowOverride None или не включен нужный модуль (часто mod_rewrite).
  • Браузер скачивает PHP-файл как текст — не настроена передача .php в PHP-FPM.

Выводы

  • Apache HTTP Server вырос в 1995 году из патчей к NCSA HTTPd; живая ветка — 2.4.x.
  • Параллельность задает MPM: prefork, worker или event; для новых установок — event плюс PHP-FPM.
  • Функциональность — в модулях; лишние стоит выключать.
  • Основной конфиг применяется после reload, .htaccess — на каждый запрос, но только в рамках AllowOverride.
  • Базовая защита — ServerTokens Prod, Options -Indexes, только TLS 1.2 и 1.3, плюс обновления и мониторинг. Применять — по чек-листу: копия, сохраненный SSH, configtest и apache2ctl -S, reload, проверка локально и снаружи, откат.

Где применяется / связь с практикой

Освойте тему на практике

Apache встречается на shared-хостингах, в корпоративных сетях и за nginx как сервер приложений. Читать его конфиг, безопасно применять изменения и разбирать ошибки по логу — базовая работа Linux-администратора. Эти навыки вместе с сетью, systemd и диагностикой разбирают на курсе Administrator Linux. Professional. Попробовать формат можно на бесплатных открытых уроках.

Смежные темы: что такое веб-сервер и как он обрабатывает HTTP-запрос, как запустить PHP на веб-сервере через Apache.

FAQ

Можно ли использовать Apache в коммерческом проекте бесплатно?
Да. Сервер распространяется по лицензии Apache License 2.0, которая разрешает коммерческое использование и модификацию при сохранении уведомлений об авторских правах и лицензии.

Apache Tomcat и Apache HTTP Server — одно и то же?
Нет. Tomcat — контейнер сервлетов для Java-приложений, а HTTP Server — универсальный веб-сервер; их часто ставят в связке через mod_proxy.

Работает ли Apache в Windows?
Да, через mpm_winnt, но фонд публикует только исходники — готовые сборки под Windows делают сторонние проекты.

OTUS Журнал
Скидка 5% 14-20 сентября на курсы (popup)