Настройка массового виртуального хостинга Apache2 с mod_rewrite, mod_userdir и mod_suexec на CentOS 5.3
Версия: 1.2
Последнее редактирование: 7 июля 2009
Кратко: этот материал показывает метод массового виртуального хостинга на Apache2 с динамическим сопоставлением директорий через mod_rewrite и запуском CGI под владельцем скрипта с помощью suEXEC и mod_userdir. Подходит для распределённого хостинга, где каждому сайту соответствует системный пользователь. Тестируйте в контролируемой среде — конфигурация не проверялась на production.
Перед началом
Платформа: CentOS 5.3. Для примера предполагается, что домен www.example.com указывает на веб‑сервер с IP 192.168.1.1, а веб‑корень example.com расположен в /home/vhosts/example.com/public_html.
Важно: CentOS 5.3 — устаревшая версия; при перенесении на современные системы проверьте совместимость модулей и пути к бинарникам.
Установка Apache
Установите пакет httpd (в пакете CentOS включены модули mod_rewrite, mod_userdir и mod_suexec):
yum install httpdКонфигурация массового виртуального хостинга
Откройте конфигурацию Apache:
vim /etc/httpd/conf/httpd.confДобавьте загрузку модуля mod_rewrite в верхней части (если ещё не загружен):
LoadModule rewrite_module modules/mod_rewrite.so
Внизу файла вставьте следующие правила (не меняйте пути, если используете ту же структуру):
## get the server name from the Host: header
UseCanonicalName Off
## splittable logs
LogFormat "%{Host}i %h %l %u %t \"%r\" %s %b" vcommon
CustomLog logs/access_log vcommon
RewriteEngine On
## Create a handle to convert upper or mixed-case to lower-case
RewriteMap lowercase int:tolower
##-----------------------------------
## where hostname has www prefix
##-----------------------------------
## Firstly create custom variable that contains the host without the www prefix
RewriteCond %{HTTP_HOST} ^www\.(.*)$
RewriteRule .? - [E=noWWWHost:%1]
## Map the virtualhost to the documentroot
RewriteCond %{REQUEST_URI} !^/~
RewriteCond %{HTTP_HOST} ^www\.
RewriteRule ^/(.*)$ /home/vhosts/${lowercase:%{ENV:noWWWHost}}/public_html/$1
##-----------------------------------
## where hostname *does not* have www prefix
##-----------------------------------
## Map the virtualhost to the documentroot
RewriteCond %{REQUEST_URI} !^/~
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^/(.*)$ /home/vhosts/${lowercase:%{HTTP_HOST}}/public_html/$1
Пояснения к конфигурации:
- Сайты размещаются в /home/vhosts. Каждая подпапка — это доменное имя сайта (без www), например /home/vhosts/example.com.
- Запрос к www.example.com будет динамически переписан на example.com.
- Документная корневая папка называется public_html — это требование suEXEC для работы через mod_userdir. Если вы не планируете использовать suEXEC, можно использовать другое имя и скорректировать правила.
Создайте тестовый index.html в public_html виртуального хоста:
echo "index.html Hello World" > /home/vhosts/example.com/public_html/index.htmlЗапустите Apache:
/etc/init.d/httpd startЗатем при обращении к http://www.example.com/ должен отобразиться текст ‘index.html Hello World’. Если нет — смотрите лог ошибок:
tail /var/log/httpd/error_logЗапуск CGI под владельцем скрипта (suEXEC + mod_userdir)
Цель: в окружении шаред‑хостинга CGI/скрипты должны запускаться от имени владельца сайта, а не от процесса веб‑сервера.
Требование: системный пользователь с именем, равным имени сайта. Пример для example.com:
useradd -d /home/vhosts/example.com example.comЭто создаст пользователя example.com с домашней директорией /home/vhosts/example.com. Веб‑файлы для www.example.com помещайте в /home/vhosts/example.com/public_html.
Можно завести пользователей вручную в /etc/passwd или интегрировать LDAP/AD для автоматической авторизации.
Включите модуль mod_userdir и настройте UserDir:
vim /etc/httpd/conf/httpd.confУбедитесь, что в конфиге присутствуют строки:
LoadModule userdir_module modules/mod_userdir.so
UserDir public_html
Теперь при запросе вида http://192.168.1.1/~example.com Apache по умолчанию будет искать /home/vhosts/example.com/public_html. Но мы хотим, чтобы URL оставался в форме http://www.example.com — для этого добавим скрытую переписку для CGI.
Добавьте после ранее вставленных правил следующее:
## Rewrite script to userdir so we can use suEXEC
RewriteCond %{REQUEST_URI} !^/~
RewriteCond %{SCRIPT_FILENAME} /home/vhosts/(.*)/public_html/(.*\.(pl|cgi))
RewriteRule .* /~%1/%2 [PT,L]
AddHandler cgi-script .pl .cgi
Options +ExecCGI
Перезагрузите конфигурацию Apache:
/etc/init.d/httpd reloadСоздайте тестовый Perl‑скрипт test.pl в public_html:
#!/usr/bin/perl
print "Content-type: text/html\n\n";
print "test.pl Hello World
\n";
Сделайте скрипт исполняемым и установите правильного владельца:
chmod +x test.plchown example.com:example.com test.plТеперь при обращении к http://www.example.com/test.pl вы должны увидеть ‘test.pl Hello World’. Если нет — проверьте логи:
tail /var/log/httpd/error_logtail /var/log/httpd/suexec.logPHP и Python через suEXEC
Добавить поддержку PHP и Python просто: установите необходимые пакеты и настройте обработку как CGI.
Установите интерпретаторы:
yum install php-cliyum install pythonПримеры скриптов в public_html:
test.py
#!/usr/bin/python
print "Content-type: text/html\n\n"
print "test.py Hello world!"
test.php
#!/usr/bin/php-cgi
echo "test.php Hello world!";
?>
Поменяйте владельца и дайте бит исполнения. Каждому скрипту нужно указывать интерпретатор в первой строке (shebang). Чтобы не править каждый файл, можно зарегистрировать binfmt_misc (требуются разрешения и поддержка ядра):
echo ":PHP:E::php::/usr/bin/php-cgi:" > /proc/sys/fs/binfmt_misc/register
echo ":Python:E::py::/usr/bin/python:" > /proc/sys/fs/binfmt_misc/registerРасширьте правило переписывания и обработчик cgi‑script:
## Rewrite script to userdir so we can use suEXEC
RewriteCond %{REQUEST_URI} !^/~
RewriteCond %{SCRIPT_FILENAME} /home/vhosts/(.*)/public_html/(.*\.(pl|cgi|php|py))
RewriteRule .* /~%1/%2 [PT,L]
AddHandler cgi-script .pl .cgi .php .py
Options +ExecCGI
PHP‑примечание: установите cgi.force_redirect = 0 в /etc/php.ini, чтобы избежать ошибок REDIRECT_STATUS при запуске php-cgi.
Перезагрузите Apache:
/etc/init.d/httpd reloadПроверяйте логи при ошибках:
tail /var/log/httpd/error_logtail /var/log/httpd/suexec.logCatchall — обработка несуществующих виртуальных хостов
Если нужно перенаправлять запросы к несуществующим vhost на «пойманный» сайт, добавьте последним правилом в /etc/httpd/conf/httpd.conf:
## Redirect non-existent virtualhosts
RewriteCond %{REQUEST_URI} !^/~
RewriteCond %{SCRIPT_FILENAME} (/home/vhosts/.*)/public_html/.*
RewriteCond %1 !-d
RewriteRule .? http://www.google.com [R,NS,L]
Замените http://www.google.com на адрес вашего catchall‑сайта. Это правило должно быть последним, чтобы не перехватывать реальные хосты.
Безопасность, ограничения и рекомендации
Important: suEXEC выполняет дополнительные проверки безопасности и ограничивает запуск CGI только в определённых условиях (пути, владельцы, права). Проверьте:
- Владелец и группа файлов совпадают с ожидаемыми (chown user:user).
- Права на директории и скрипты не должны быть открыты для группы/остальных (обычно 0755 для директорий и 0755/0750 для скриптов, уточняйте по требованиям suEXEC).
- suEXEC логирует сообщения в /var/log/httpd/suexec.log — используйте его для отладки.
Ограничения suEXEC и mod_userdir:
- suEXEC не поддерживает запуск из произвольных путей — путь и владельцы должны соответствовать ожиданиям.
- suEXEC не выполняет файлы с небезопасными правами.
- Если нужны ресурсоёмкие приложения (persistent PHP-FPM, long‑running Python), лучше использовать отдельные процессы/сокеты вместо suEXEC CGI.
Рекомендации по безопасности:
- Минимизируйте набор исполняемых расширений (.pl, .cgi, .php, .py).
- Используйте SELinux (если включён) и настройте политики для каталога /home/vhosts.
- Отключите ненужные модули Apache и ограничьте число разрешённых директив в .htaccess.
Чек‑лист перед запуском (роль: системный администратор)
- Установлен пакет httpd.
- Загружены модули mod_rewrite, mod_userdir, mod_suexec.
- В каталоге /home/vhosts созданы директории для доменов.
- Пользователи созданы и владеют своими директориями (useradd -d …).
- public_html присутствует и содержит index.html для теста.
- Конфигурация RewriteMap и правил проверена локально.
- Тестовые CGI‑скрипты имеют правильные shebang, права и владельца.
- Логи доступны и индексируются для отладки (/var/log/httpd/*).
Критерии приёмки
- При обращении к существующему домену отображается его index.html.
- CGI/Perl/Python/PHP скрипт запускается и возвращает корректный HTTP‑ответ от имени владельца сайта.
- Логи Apache и suexec не содержат ошибок при штатных запросах.
- Правило catchall срабатывает только для несуществующих сайтов.
Runbook: быстрый порядок действий при сбое
- Проверить статус httpd: systemctl (или /etc/init.d/httpd) start|status.
- Просмотреть последние записи в /var/log/httpd/error_log и /var/log/httpd/suexec.log.
- Проверить, что каталог и файл существуют и имеют правильные права: ls -l /home/vhosts/example.com/public_html/test.pl.
- Убедиться, что shebang у скрипта корректен и интерпретатор установлен.
- Откат: восстановить предыдущую конфигурацию httpd.conf из резервной копии и выполнить reload.
Тестовые случаи и приёмочные проверки
- Тест 1: GET / -> index.html, код 200.
- Тест 2: GET /test.pl -> выполняется тест.pl, отображает H1, владелец процесса соответствует владельцу файла.
- Тест 3: GET /test.php и /test.py -> корректный вывод от php-cgi и python.
- Тест 4: Запрос к несуществующему домену -> редирект на catchall (если включено).
Модель принятия решений (Mermaid)
flowchart TD
A[Запрос на www.example.com] --> B{Существует ли /home/vhosts/domain/public_html}
B -- Да --> C{Запрошен файл с расширением CGI?}
C -- Да --> D[Переписать на /~user/file и запустить suEXEC]
C -- Нет --> E[Отдать файл из /home/vhosts/domain/public_html]
B -- Нет --> F[Сработает правило catchall или 404]Совместимость и миграция
- На новых дистрибутивах пути к php-cgi и python могут отличаться (/usr/bin/php-cgi, /usr/bin/python3). Проверьте shebang.
- CentOS 5.3 — устаревший релиз. При переносе на более новые системы рассмотрите использование PHP‑FPM, systemd и современных механизмов изоляции (containers, cgroups) вместо suEXEC для лучшей масштабируемости.
Частые ошибки и способы устранения
- Ошибка suEXEC: проверьте владельца и права файла.
- Ошибка CGI REDIRECT_STATUS: установите cgi.force_redirect = 0 в /etc/php.ini.
- Переписывание не срабатывает: включён ли мод_rewrite и правильны ли условия RewriteCond.
- Нечитаемые логи: проверьте права на /var/log/httpd и r/o монтирование.
Роль‑ориентированные чек‑листы
Администратор:
- Провести аудит прав и владельцев.
- Настроить ротацию логов.
- Настроить мониторинг доступности.
Разработчик:
- Проверить shebang и зависимости скрипта.
- Убедиться, что скрипт не требует persistent‑процесса.
Короткое резюме
- Массовый виртуальный хостинг реализуется через динамическую переписку путей в mod_rewrite и размещение сайтов в /home/vhosts.
- suEXEC + mod_userdir позволяют запускать CGI от владельца сайта.
- Проверяйте права, shebang и логи; на современных платформах рассмотрите альтернативы suEXEC для лучшей производительности.
Важно: эта инструкция описывает один из подходов. Для production рекомендуется тестирование на staging, контроль прав доступа, бекапы конфигурации и, при необходимости, миграция на современные механизмы обработки скриптов.
Похожие материалы
Как улучшить графику в Elden Ring
Удаление пароля Windows 10 для локальной учётной записи
HANDLE_ERROR_ON_CRITICAL_THREAD — как исправить BSOD
Устранение утечки памяти LockAppHost.exe в Windows 10
Ошибка AppHangB1: способы исправления