Apache HTTP 服务器
Apache HTTP 服务器,或简称 Apache,是由 Apache 软件基金会开发的非常流行的 Web 服务器。
本文介绍如何设置 Apache,以及如何选择性地将其与 PHP 集成。
安装
配置
Apache 配置文件位于 /etc/httpd/conf 目录中。主配置文件是 /etc/httpd/conf/httpd.conf,它包含了各种其他配置文件。默认配置文件对于简单设置来说应该足够好。默认情况下,它会将 /srv/http 目录提供给任何访问您网站的人。
要运行 Apache,启动 httpd.service。如果一切正常,访问 https:/// 应该会显示一个简单的索引页面。
有关可选的进一步配置,请参阅以下章节。
高级选项
请参阅 Apache 配置指令的完整列表 和 指令快速参考。
在 /etc/httpd/conf/httpd.conf 中的这些选项可能对您有用
User http
- 出于安全原因,一旦 Apache 由 root 用户(直接或通过启动脚本)启动,它就会切换到此 UID。默认用户是 http,它在安装过程中自动创建。
Listen 80
- 这是 Apache 将监听的端口。对于通过路由器进行互联网访问,您必须转发端口。
- 如果您想为本地开发设置 Apache,您可能希望它只能从您的计算机访问。然后将此行更改为
Listen 127.0.0.1:80。
ServerAdmin you@example.com
- 这是管理员的电子邮件地址,可以在错误页面等地方找到。
DocumentRoot "/srv/http"
- 这是您应该放置网页的目录。
- 如果您想更改它,请更改它,但不要忘记将
<Directory "/srv/http">也更改为您更改DocumentRoot的任何内容,否则当您尝试访问新的文档根目录时,可能会收到 403 错误(缺少权限)。不要忘记将Require all denied行更改为Require all granted,否则您将收到 403 错误。请记住,DocumentRoot目录及其父文件夹必须允许其他人执行权限(可以使用chmod o+x /path/to/DocumentRoot设置),否则您将收到 403 错误。
AllowOverride None
- 在
<Directory>部分中的此指令导致 Apache 完全忽略.htaccess文件。请注意,这现在是 Apache 2.4 的默认设置,因此如果您计划使用.htaccess文件,则需要显式允许覆盖。如果您打算在.htaccess文件中使用mod_rewrite或其他设置,您可以允许该文件中声明的哪些指令可以覆盖服务器配置。有关更多信息,请参阅 Apache 文档。
apachectl configtest更多设置可以在 /etc/httpd/conf/extra/httpd-default.conf 中找到
关闭服务器签名
ServerSignature Off
隐藏服务器信息,如 Apache 和 PHP 版本
ServerTokens Prod
用户目录
用户目录默认通过 https:///~yourusername/ 可用,并显示 ~/public_html 的内容(这可以在 /etc/httpd/conf/extra/httpd-userdir.conf 中更改)。
如果您不希望用户目录在 Web 上可用,请注释掉 /etc/httpd/conf/httpd.conf 中的以下行
Include conf/extra/httpd-userdir.conf
您必须确保您的主目录权限设置正确,以便 Apache 可以访问那里。您的主目录和 ~/public_html 必须对其他人(“世界其他地方”)可执行
$ chmod o+x ~ $ chmod o+x ~/public_html $ chmod -R o+r ~/public_html
重启 httpd.service 以应用任何更改。另请参阅 Umask#设置掩码值。
TLS
首先获取证书。如果您拥有公共域名,则可以使用 传输层安全性#ACME 客户端。
在 /etc/httpd/conf/httpd.conf 中,取消注释以下三行
LoadModule ssl_module modules/mod_ssl.so LoadModule socache_shmcb_module modules/mod_socache_shmcb.so Include conf/extra/httpd-ssl.conf
如果使用 Certbot (certbot --apache),则还需要取消注释以下行
LoadModule rewrite_module modules/mod_rewrite.so
获取密钥和证书后,请确保 /etc/httpd/conf/extra/httpd-ssl.conf 中的 SSLCertificateFile 和 SSLCertificateKeyFile 行指向密钥和证书。如果还生成了 CA 证书的串联链,请将该文件名添加到 SSLCertificateChainFile。
最后,重启 httpd.service 以应用任何更改。
虚拟主机
<VirtualHost *:443> 部分。有关示例文件,请参阅 #管理多个虚拟主机。如果您想拥有多个主机,请取消注释 /etc/httpd/conf/httpd.conf 中的以下行
Include conf/extra/httpd-vhosts.conf
在 /etc/httpd/conf/extra/httpd-vhosts.conf 中设置您的虚拟主机。默认文件包含一个详细的示例,应该可以帮助您入门。
要在本地计算机上测试虚拟主机,请将虚拟名称添加到您的 /etc/hosts 文件中
127.0.0.1 domainname1.dom 127.0.0.1 domainname2.dom
重启 httpd.service 以应用任何更改。
管理多个虚拟主机
如果您有大量的虚拟主机,您可能希望轻松地禁用和启用它们。建议为每个虚拟主机创建一个配置文件,并将它们都存储在一个文件夹中,例如:/etc/httpd/conf/vhosts。
首先创建文件夹
# mkdir /etc/httpd/conf/vhosts
然后将单个配置文件放在其中
# nano /etc/httpd/conf/vhosts/domainname1.dom # nano /etc/httpd/conf/vhosts/domainname2.dom ...
在最后一步中,在您的 /etc/httpd/conf/httpd.conf 中 Include 单个配置
#Enabled Vhosts: Include conf/vhosts/domainname1.dom Include conf/vhosts/domainname2.dom
您可以通过注释或取消注释单个虚拟主机来启用和禁用它们。
一个非常基本的 vhost 文件将如下所示
/etc/httpd/conf/vhosts/domainname1.dom
<VirtualHost *:80>
ServerAdmin webmaster@domainname1.dom
DocumentRoot "/home/user/http/domainname1.dom"
ServerName domainname1.dom
ServerAlias domainname1.dom
ErrorLog "/var/log/httpd/domainname1.dom-error_log"
CustomLog "/var/log/httpd/domainname1.dom-access_log" common
<Directory "/home/user/http/domainname1.dom">
Require all granted
</Directory>
</VirtualHost>
<VirtualHost *:443>
ServerAdmin webmaster@domainname1.dom
DocumentRoot "/home/user/http/domainname1.dom"
ServerName domainname1.dom:443
ServerAlias domainname1.dom:443
SSLEngine on
SSLCertificateFile "/etc/httpd/conf/server.crt"
SSLCertificateKeyFile "/etc/httpd/conf/server.key"
ErrorLog "/var/log/httpd/domainname1.dom-error_log"
CustomLog "/var/log/httpd/domainname1.dom-access_log" common
<Directory "/home/user/http/domainname1.dom">
Require all granted
</Directory>
</VirtualHost>
扩展
PHP
首先安装 PHP,然后按照下面接下来的三个子章节之一进行操作。最后,按照最后一个子章节中的描述测试安装。
使用 libphp
此方法可能是最简单的,但也是可伸缩性最差的:它适用于轻请求负载。它还要求您更改 mpm 模块,这可能会导致其他扩展出现问题(例如,它与 #HTTP/2 不兼容)。
在 /etc/httpd/conf/httpd.conf 中,注释掉该行
#LoadModule mpm_event_module modules/mod_mpm_event.so
并取消注释该行
LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
libphp.so 不适用于 mod_mpm_event,而仅适用于 mod_mpm_prefork。(FS#39218)否则您将收到以下错误
Apache is running a threaded MPM, but your PHP Module is not compiled to be threadsafe. You need to recompile PHP. AH00013: Pre-configuration failed httpd.service: control process exited, code=exited status=1作为替代方案,您可以使用
mod_proxy_fcgi(请参阅下面的 #使用 php-fpm 和 mod_proxy_fcgi)。要启用 PHP,请将以下行添加到 /etc/httpd/conf/httpd.conf
- 将其放在
LoadModule列表的末尾
LoadModule php_module modules/libphp.so AddHandler php-script .php
- 将其放在
Include列表的末尾
Include conf/extra/php_module.conf
然后重启 httpd.service。
php_module、libphp.so 和 php_module.conf。 例如,对于 php56-apacheAUR,应替换为 php5_module、libphp56.so 和 php56-module.conf。
pacman -Ql phpXX-apache 列出 libphp.so 和 php_module.conf 的正确替换,然后使用 nm /usr/lib/httpd/modules/libphpXX.so 查找 php_module 的正确替换。使用 apache2-mpm-worker 和 mod_fcgid
此方法在处理多个请求时提供更好的性能和内存使用率。
创建所需的目录并为其 PHP 包装器创建符号链接
# mkdir /srv/http/fcgid-bin # ln -s /usr/bin/php-cgi /srv/http/fcgid-bin/php-fcgid-wrapper
创建 /etc/httpd/conf/extra/php-fcgid.conf,内容如下
/etc/httpd/conf/extra/php-fcgid.conf
# Required modules: fcgid_module
<IfModule fcgid_module>
AddHandler php-fcgid .php
AddType application/x-httpd-php .php
Action php-fcgid /fcgid-bin/php-fcgid-wrapper
ScriptAlias /fcgid-bin/ /srv/http/fcgid-bin/
SocketPath /var/run/httpd/fcgidsock
SharememPath /var/run/httpd/fcgid_shm
# If you don't allow bigger requests many applications may fail (such as WordPress login)
FcgidMaxRequestLen 536870912
# Path to php.ini – defaults to /etc/phpX/cgi
DefaultInitEnv PHPRC=/etc/php/
# Number of PHP childs that will be launched. Leave undefined to let PHP decide.
#DefaultInitEnv PHP_FCGI_CHILDREN 3
# Maximum requests before a process is stopped and a new one is launched
#DefaultInitEnv PHP_FCGI_MAX_REQUESTS 5000
<Location /fcgid-bin/>
SetHandler fcgid-script
Options +ExecCGI
</Location>
</IfModule>
编辑 /etc/httpd/conf/httpd.conf
- 取消注释 actions 模块的加载行
LoadModule actions_module modules/mod_actions.so
- 在加载 unixd 模块之后加载 FCGID 模块(它依赖于 unixd 模块) - 您可能希望将其放置在
<IfModule unixd_module>代码块中LoadModule fcgid_module modules/mod_fcgid.so
- 确保 MPM 配置的包含行已取消注释(在默认安装的此文件中,它是取消注释的)
Include conf/extra/httpd-mpm.conf
- 添加新 FCGID 配置的包含行
Include conf/extra/php-fcgid.conf
重启 httpd.service。
使用 php-fpm 和 mod_proxy_fcgi
此方法提供了“另一种 PHP FastCGI 实现,它具有一些额外的功能,(主要)对高负载站点有用” [1]。
ProxyPassMatch ^/(.*\.php(/.*)?)$ unix:/run/php-fpm/php-fpm.sock|fcgi:///srv/http/$1
启用 proxy 模块
/etc/httpd/conf/httpd.conf
LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
创建 /etc/httpd/conf/extra/php-fpm.conf,内容如下
DirectoryIndex index.php index.html
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php-fpm/php-fpm.sock|fcgi:///"
</FilesMatch>
并将其包含在 /etc/httpd/conf/httpd.conf 的底部
Include conf/extra/php-fpm.conf
您可以在 /etc/php/php-fpm.d/www.conf 中配置 PHP-FPM,但默认设置应该可以正常工作。
启动 并 启用 php-fpm.service,然后 重启 httpd.service。
测试 PHP 是否工作
要测试 PHP 是否配置正确,请在您的 Apache DocumentRoot 目录(例如 /srv/http/ 或 ~<username>/public_html/)中创建一个名为 test.php 的文件,内容如下
<?php phpinfo(); ?>
然后访问 https:///test.php 或 https:///~<username>/test.php,视情况而定。
HTTP/2
- 虽然 Apache 支持通过 TCP 的未加密 HTTP/2 (
h2c),但常见的浏览器不支持。 因此,为了与后者一起使用,必须首先启用 #TLS。 - 如果支持的客户端没有使用 HTTP/2 而不是 HTTP/1.1,并且 Mozilla 的配置生成器(已经包含下面的
Protocols行)被用于设置 #TLS,请尝试在后者的输出之后Include包含httpd-ssl.conf。 - 测试方法包括
curl -sI https://your.website或使用 http indicator(支持基于 Chromium 的浏览器和基于 Firefox 的浏览器)。
要启用通过 TLS 的 HTTP/2 支持,请取消注释 httpd.conf 中的以下行
LoadModule http2_module modules/mod_http2.so
并添加以下行
Protocols h2 http/1.1
要进行调试,您可以仅将模块而不是整个服务器设置为 debug 或 info
<IfModule http2_module>
LogLevel http2:info
</IfModule>
有关更多信息(包括额外的 HTTP/2 功能设置),请参阅 mod_http2 文档。
故障排除
Apache 状态和日志
使用 systemctl 查看 Apache 守护进程的状态。
Apache 日志可以在 /var/log/httpd/ 中找到
错误:启动后 PID 文件 /run/httpd/httpd.pid 不可读(尚未?)
注释掉 httpd.conf 中的 unique_id_module 行: #LoadModule unique_id_module modules/mod_unique_id.so
/run/httpd 未在启动时创建
如果 root 用户执行 systemd-tmpfiles --create 时抱怨“unsafe path transition”,请检查您的根目录的所有权。
ls -la / chown root:root /
Apache 正在运行线程化的 MPM,但您的 PHP 模块未编译为线程安全。
如果在加载 php_module 时 httpd.service 失败,您可能会在日志中收到类似这样的错误
Apache is running a threaded MPM, but your PHP Module is not compiled to be threadsafe. You need to recompile PHP.
这是因为 PHP 包含对非线程安全模块的支持,并且您正在尝试使用线程化的 MPM。 解决此问题的一种方法是使用非线程化的 MPM。 尝试将 mpm_event_module 替换为 mpm_prefork_module
/etc/httpd/conf/httpd.conf
LoadModule mpm_event_module modules/mod_mpm_event.soLoadModule mpm_prefork_module modules/mod_mpm_prefork.so
并重启 httpd.service。
http2_module)在 mpm_prefork 激活时会禁用自身。AH00534: httpd: Configuration error: No MPM loaded.
您可能在最近的升级后遇到此错误。 这只是 httpd.conf 中最近更改的结果,您可能尚未在本地配置中重现该更改。 要修复它,请取消注释以下行
/etc/httpd/conf/httpd.conf
LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
并重启 httpd.service。
AH00072: make_sock: could not bind to address
这可能是由多种原因引起的。 最常见的问题是某些东西已经在给定的端口上监听,通过 ss 检查是否发生这种情况
# ss -lnp | grep -e :80 -e :443
如果您得到任何输出,请停止占用端口的给定服务或杀死导致端口绑定的失控进程,然后重试。
另一个问题可能是 Apache 没有以 root 身份启动 - 尝试手动启动它,看看是否仍然收到 AH0072 错误。
# httpd -k start
最后,您的配置也可能存在错误,并且您在给定端口上监听了两次。 以下是一个错误配置的示例,它将触发此问题
Listen 0.0.0.0:80 Listen [::]:80
AH01071: Got error 'Primary script unknown'
如果您在虚拟主机环境中为 /home 中的文件提供服务,则可能是 php-fpm systemd 单元文件中 ProtectHome=true 引起的。 您可以通过编辑 php-fpm 单元文件并重启 php-fpm.service 来禁用此功能。 或者,移动您的文档根目录。
更改 php.ini 中的 max_execution_time 无效
如果您在 php.ini 中将 max_execution_time 更改为大于 30(秒)的值,您仍然可能会在 30 秒后从 Apache 收到 503 Service Unavailable 响应。 要解决此问题,请在 <FilesMatch \.php$> 代码块之前在您的 http 配置中添加 ProxyTimeout 指令
/etc/httpd/conf/httpd.conf
ProxyTimeout 300
并重启 httpd.service。
PHP-FPM:错误没有按虚拟主机单独记录
如果您有多个虚拟主机,则可能希望将每个虚拟主机的错误日志输出到单独的文件(使用 ErrorLog Apache 指令)。 如果这对您不起作用,请确认 PHP-FPM 配置为将错误记录到 syslog
/etc/php/php-fpm.conf
error_log = syslog
池配置也可能覆盖它。 确保以下行被注释掉
/etc/php/php-fpm.d/www.conf
;php_admin_value[error_log] = /var/log/fpm-php.www.log
另请参阅
- Apache 官方网站
- Apache 文档
- Apache wiki
- Apache 文档 - 安全提示
- Apache Wiki - 故障排除
- Apache 在 wiki.debian.org 上