如何使用Apache HTTP服务器在“默认设置”下运行
NRI OpenStandia Advent Calendar 2020的第8天,我们将讨论Apache HTTP Server。
首先
Apache HTTP服务器(以下简称Apache)是一个经常被使用的Web服务器,但对于不熟悉的人来说,设置可能会很困难。
我认为Apache的“默认配置文件”很复杂,这可能导致许多人对其感到不适应。因此,这次我想写一篇文章,介绍如何使用“默认配置值”来运行Apache,而不是使用默认配置文件。
基本知识
默认配置文件 vs 默认配置值
在Apache配置中,有两种常被称为”默认值”的设置。
-
- 如果没有在安装后的配置文件中设置值(默认配置文件的值),
- 那么将使用为配置文件中未设置的值(默认设置值)。
由于前者可以在安装后立即看到,因此它的存在很容易被注意到,但是许多人会在不知不觉中使用后者。毕竟,Apache有695种配置指令可用,并且并不是所有配置都在默认配置文件中写明,所以大多数人甚至不知道它的存在,仍然使用默认的第二个配置值。
然而,如果有第2个默认设置值,那么第1个默认设置文件的值有什么意义呢?我认为这可能是立场上的不同。
默认设置值没有设置任何”多余”的功能,包括访问控制,也有些地方不方便使用。然而,默认设置文件设置了访问控制,采用了”默认安全”的思想,并且适度地进行了设置,使其可以立即使用。
然而,如果许多人因此而感到不善于使用Apache,那将是遗憾的。
大量的默认设置文件配置
无论是从Apache开发方的源代码安装还是从各种Linux发行版附带的软件包安装,安装过程中都会放置大量的配置,而且非常复杂。
为了解释以下内容,我们启动了官方Docker镜像并尝试进入其中。
# docker run -t -i --rm httpd:2.4.46 bash
基本上,無論是通過Docker安裝還是從官方源代碼安裝,都是一樣的。
我会尝试计算安装后设置文件的行数。
# wc -l /usr/local/apache2/conf/httpd.conf
551 httpd.conf
551行!除了设置之外,大部分都是为了解释而添加的注释,不过还是太多了。
默认值的实例(日志级别)
默认设置文件的第324行附近有以下LogLevel指令。这是日志输出级别的配置。
# LogLevel: Control the number of messages logged to the error_log.
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
#
LogLevel warn
假设不进行此设置,则将使用“默认设置值”。让我们查看LogLevel的默认值。此信息在手册中有详细说明。

如果在设置文件中没有写入LogLevel日志级别,由于默认情况下有 “デフォルト: LogLevel warn” 的描述,它将被设定为warn级别。因此,如果有这个描述,而且没有必要将日志级别设为其他级别,那么在设置文件中写下这个描述是不必要的,可以毅然删除它,这也是一种思考方式。
让我们尝试使用默认设置值来运行。
终于要进入标题的话题了。
不仅仅是针对LogLevel,既然已经有默认设置值,为什么不先使用默认设置值运行,如果默认设置值不行的话,再逐步添加配置呢?因此,我尝试了一下。
首先,大胆地將設定文件清空一試。
# echo > /usr/local/apache2/conf/httpd.conf
我只需要一个选项:
这样设置后,Apache是否能正常运行?我将尝试启动。
# apachectl start
AH00534: httpd: Configuration error: No MPM loaded.
很遗憾,无法使用完全空的配置文件进行启动。
因为完全空的配置文件除了核心模块以外,其他模块都不存在,所以也没有MPM[^1]。由于MPM是必须的,所以会导致错误。
解决方法很简单,只需添加要加载的配置即可。这次我们将加载Event MPM并尝试重新启动。
如果在编译时指定了模块内嵌选项,则不适用上述规则。在官方Docker镜像中,模块没有被内嵌,需要使用LoadModule来加载所需模块。
# echo "LoadModule mpm_event_module modules/mod_mpm_event.so" >> httpd.conf
# apachectl start
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
no listening sockets available, shutting down
AH00015: Unable to open logs
听起来还是不行。
据说没有可用的监听套接字,为什么呢?
关于这个问题,在Listen指令的手册中有清楚的说明。
http://httpd.apache.org/docs/2.4/mod/mpm_common.html#listen
请注意,现在Listen指令已成为必要指令。如果在配置文件中未找到该指令,则服务器将无法启动。
默认情况下并不是在端口80上启动,是吗?我会立即添加设置并启动。
# echo "Listen 80" >> httpd.conf
# apachectl start
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
哇,你成功启动了吗?
# ps aux | grep http[d]
#
无法启动!让我们查看错误日志。
# cat ../logs/error_log
[Sun Dec 06 16:40:51.544435 2020] [core:crit] [pid 17:tid 140427119510656] AH00136: Server MUST relinquish startup privileges before accepting connections. Please ensure mod_unixd or other system security module is loaded.
AH00016: Configuration Failed
请载入mod_unixd,或类似模块。尽管在mod_unixd的手册中没有特别的模块说明,如果没有先备知识的话,可能会感到困惑。然而,需要注意的是,存在着User和Group这两个指令。简单来说,这个模块主要用于在Unix类操作系统上使用Apache时,在以root权限启动后切换(降低)运行用户和用户组的权限。
让我们尝试加载mod_unixd。
# echo "LoadModule unixd_module modules/mod_unixd.so" >> httpd.conf
# apachectl start
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
这一次已经启动了吗?
# ps aux | grep http[d]
root 599 0.0 0.0 5284 3320 ? Ss 17:08 0:00 /usr/local/apache2/bin/httpd -k start
root 600 0.0 0.0 1996392 11284 ? Sl 17:08 0:00 /usr/local/apache2/bin/httpd -k start
root 601 0.0 0.0 1996392 11348 ? Sl 17:08 0:00 /usr/local/apache2/bin/httpd -k start
root 602 0.0 0.0 1996392 11320 ? Sl 17:08 0:00 /usr/local/apache2/bin/httpd -k start

500错误…
以下错误已经出现。
[Sun Dec 06 17:13:19.243024 2020] [core:crit] [pid 12:tid 140695037785856] [client 172.17.0.1:59724] AH00025: configuration error: couldn't check user: /
Apache中有一个名为mod_authz_core的模块,用于检查用户是否有访问权限。尝试加载该模块。
# echo "LoadModule authz_core_module modules/mod_authz_core.so" >> httpd.conf
# apachectl stop
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
# apachectl start
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message

总结
要将Apache以默认设置值运行,需要进行以下4行设置。
LoadModule mpm_event_module modules/mod_mpm_event.so
Listen 80
LoadModule unixd_module modules/mod_unixd.so
LoadModule authz_core_module modules/mod_authz_core.so
这三行中的LoadModule仅加载了模块,所以可以说只有Listen是唯一必需的设置。除此之外,其他都是使用默认设置值。
通过添加所需的设置,可以创建自己的Apache配置。请大家一定要尝试一下。