Apache HTTP 服务器
Apache HTTP 服务器,或简称 Apache,是由 Apache 软件基金会开发的非常流行的 Web 服务器。
本文介绍如何设置 Apache,以及如何选择性地将其与 PHP 集成。
安装
配置
Apache 配置文件位于 /etc/httpd/conf
目录中。主配置文件是 /etc/httpd/conf/httpd.conf
,它包含了各种其他配置文件。默认配置文件对于简单设置来说应该足够好。默认情况下,它会将 /srv/http
目录提供给任何访问您网站的人。
要运行 Apache,启动 httpd.service
。如果一切正常,访问 https://127.0.0.1/ 应该会显示一个简单的索引页面。
有关可选的进一步配置,请参阅以下章节。
高级选项
请参阅 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://127.0.0.1/~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://127.0.0.1/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://127.0.0.1/" </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://127.0.0.1/test.php 或 https://127.0.0.1/~<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 上