Apache HTTP Server
Apache HTTP Server(简称 Apache)是一个非常流行的网络服务器,由 Apache 软件基金会开发。
本文介绍了如何设置 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">,否则在访问新的文档根目录时,您很可能会收到 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 Web 服务器具有遍历用户主目录并访问 ~/public_html 内文件的足够权限。目录遍历需要在路径中的每个父目录上拥有执行 (+x) 权限,这独立于目标文件上的读取 (r) 权限。
推荐的方法是使用 访问控制列表 (ACL) 仅授予 http 用户访问权限
$ setfacl -m u:http:x ~ $ setfacl -R -m u:http:rx ~/public_html
避免使用全局可执行权限(例如 chmod o+x),因为这会削弱您主目录的安全性。
您还需要在嵌入式文件 /etc/systemd/system/httpd.service.d/hardening.conf 中编辑 systemd 服务的配置
[Service] ProtectHome=no
执行 daemon-reload 并 重启 httpd.service 以应用更改。另请参阅 Umask#设置掩码值。
TLS
首先获取证书。如果您拥有公共域名,则可以使用 传输层安全性 (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> 部分以支持虚拟主机 SSL。请参阅 #管理多个虚拟主机 获取示例文件。如果您想拥有多个主机,请取消注释 /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
您可以通过注释或取消注释来启用和禁用单个虚拟主机。
一个非常基础的虚拟主机文件如下所示
/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 children 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
Require all granted
</Location>
</IfModule>
编辑 /etc/httpd/conf/httpd.conf
- 取消注释对 actions 模块的加载
LoadModule actions_module modules/mod_actions.so
- 在加载 unixd 模块(它依赖于此模块)之后加载 FCGID 模块 - 您可能希望将其放在
<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
启用代理模块
/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,请尝试在后者的输出之后Includehttpd-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。
mpm_prefork 激活时,其他一些模块(如 http2_module)会自动禁用。AH00534: httpd: 配置错误:未加载 MPM。
最近升级后您可能会遇到此错误。这仅仅是 httpd.conf 中最近的更改导致的,您可能没有在本地配置中同步这些更改。要修复它,请取消注释以下行
/etc/httpd/conf/httpd.conf
LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
并 重启 httpd.service。
AH00072: make_sock: 无法绑定到地址
这可能是由多种原因引起的。最常见的问题是某些内容已经在监听给定端口,请通过 ss 检查这种情况
# ss -lnp | grep -e :80 -e :443
如果有任何输出,请停止占用该端口的特定服务或杀死导致端口被绑定的失控进程,然后重试。
另一个问题可能是 Apache 出于某种原因没有以 root 身份启动 - 尝试手动启动它,看看是否仍然收到 AH0072 错误。
# httpd -k start
最后,您的配置也可能存在错误,即您在给定端口上监听了两次。以下是会导致此问题的错误配置示例
Listen 0.0.0.0:80 Listen [::]:80
AH01071: 收到错误 '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 on wiki.debian.org