# 32.9.Apache HTTP 服务器

开源的 Apache HTTP 服务器是最广泛使用的 web 服务器。FreeBSD 默认并未安装此 web 服务器，但可以通过 [www/apache24](https://cgit.freebsd.org/ports/tree/www/apache24/) 软件包和 Ports 进行安装。

本节总结了如何在 FreeBSD 上配置和启动版本 2.*x* 的 Apache HTTP 服务器。有关 Apache 2.X 及其配置指令的更详细信息，请参阅 [httpd.apache.org](http://httpd.apache.org/)。

## 32.9.1. 配置和启动 Apache

在 FreeBSD 中，Apache HTTP 服务器的主配置文件安装在 **/usr/local/etc/apache2x/httpd.conf**，其中 *x* 代表版本号。这个 ASCII 文本文件以 `#` 开头注释行。最常修改的指令有：

`ServerRoot "/usr/local"`

指定 Apache 安装的默认目录层次结构。二进制文件存储在服务器根目录的 **bin** 和 **sbin** 子目录中，配置文件存储在 **etc/apache2x** 子目录中。

`ServerAdmin you@example.com`

将此项更改为接收服务器问题的电子邮件地址。此地址也会出现在一些服务器生成的页面上，如错误文档。

`ServerName www.example.com:80`

允许管理员设置一个主机名，该主机名会返回给客户端。例如，可以使用 `www` 代替实际的主机名。如果系统没有注册的 DNS 名称，请输入其 IP 地址。如果服务器将监听其他端口，请将 `80` 改为其他端口号。

`DocumentRoot "/usr/local/www/apache2_x_/data"`

指定文档的根目录，默认情况下，所有请求都来自此目录，但可以使用符号链接和别名指向其他位置。

在进行更改之前，最好先备份 Apache 配置文件。配置完成后，保存文件并使用 `apachectl` 验证配置。运行 `apachectl configtest` 应返回 `Syntax OK`。

要在系统启动时启动 Apache，请在 **/etc/rc.conf** 中添加以下行：

```sh
apache24_enable="YES"
```

如果 Apache 需要以非默认选项启动，可以在 **/etc/rc.conf** 中添加以下行来指定所需的标志：

```sh
apache24_flags=""
```

如果 `apachectl` 没有报告配置错误，现在启动 `httpd`：

```sh
# service apache24 start
```

可以通过在 web 浏览器中输入 `http://localhost` 来测试 `httpd` 服务，将 *localhost* 替换为运行 `httpd` 的机器的完全限定域名。默认显示的网页是 **/usr/local/www/apache24/data/index.html**。

在 `httpd` 运行时，进行后续配置更改后，可以使用以下命令测试 Apache 配置是否有错误：

```sh
# service apache24 configtest
```

> **注意**
>
> 需要注意的是，`configtest` 不是 [rc(8)](https://man.freebsd.org/cgi/man.cgi?query=rc\&sektion=8\&format=html) 标准，不能期望它适用于所有启动脚本。

## 32.9.2. 虚拟主机

虚拟主机允许多个网站在一个 Apache 服务器上运行。虚拟主机可以是 *基于 IP 的* 或 *基于名称的*。基于 IP 的虚拟主机为每个网站使用不同的 IP 地址。基于名称的虚拟主机使用客户端的 HTTP/1.1 头部来确定主机名，从而允许多个网站共享同一个 IP 地址。

要配置 Apache 使用基于名称的虚拟主机，请为每个网站添加一个 `VirtualHost` 块。例如，对于名为 `www.domain.tld` 的 web 服务器和虚拟域 `www.someotherdomain.tld`，可以在 **httpd.conf** 文件中添加以下条目：

```ini
<VirtualHost *>
    ServerName www.domain.tld
    DocumentRoot /www/domain.tld
</VirtualHost>

<VirtualHost *>
    ServerName www.someotherdomain.tld
    DocumentRoot /www/someotherdomain.tld
</VirtualHost>
```

对于每个虚拟主机，将 `ServerName` 和 `DocumentRoot` 的值替换为要使用的值。

有关设置虚拟主机的更多信息，请参考 Apache 官方文档：<http://httpd.apache.org/docs/vhosts/>。

## 32.9.3. Apache 模块

Apache 使用模块来增强基本服务器所提供的功能。有关可用模块的完整列表及其配置细节，请参阅 <http://httpd.apache.org/docs/current/mod/>。

在 FreeBSD 中，某些模块可以通过 Port [www/apache24](https://cgit.freebsd.org/ports/tree/www/apache24/) 编译。在 **/usr/ports/www/apache24** 目录中输入 `make config` 以查看哪些模块可用，以及哪些模块是默认启用的。如果该模块未随端口一起编译，FreeBSD Ports 提供了便捷的方式来安装许多模块。本节描述了三种最常用的模块。

### 32.9.3.1. SSL 支持

曾几何时，Apache 中对 SSL 的支持需要一个名为 **mod\_ssl** 的附加模块。如今，默认安装的 Apache 已经内建了 SSL 支持。有关如何启用 SSL 网站支持的示例，请参见 **/usr/local/etc/apache24/extra** 目录中的已安装文件 **httpd-ssl.conf**。该目录中还包含一个名为 **ssl.conf-sample** 的示例文件。建议检查这两个文件，以正确设置 Apache web 服务器的安全网站。

SSL 配置完成后，必须在主 **httpd.conf** 中取消注释以下行，以便在下次重启或重新加载 Apache 时激活更改：

```sh
#Include etc/apache24/extra/httpd-ssl.conf
```

> **警告**
>
> SSL 版本 2 和版本 3 已知存在漏洞问题。强烈建议启用 TLS 版本 1.2 和 1.3 来替代较旧的 SSL 选项。可以通过在 **ssl.conf** 中设置以下选项来实现：

```ini
SSLProtocol all -SSLv3 -SSLv2 +TLSv1.2 +TLSv1.3
SSLProxyProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
```

要完成 SSL 的配置，必须取消注释以下行，确保在 Apache 重启或重新加载时将配置加载：

```ini
# 安全 (SSL/TLS) 链接
Include etc/apache24/extra/httpd-ssl.conf
```

此外，还必须取消注释 **httpd.conf** 中以下几行，以完全支持 Apache 中的 SSL：

```ini
LoadModule authn_socache_module libexec/apache24/mod_authn_socache.so
LoadModule socache_shmcb_module libexec/apache24/mod_socache_shmcb.so
LoadModule ssl_module libexec/apache24/mod_ssl.so
```

下一步是与证书颁发机构合作，安装适当的证书。这将为网站建立信任链，并防止出现自签名证书的警告。

### 32.9.3.2. **mod\_perl**

**mod\_perl** 模块使得可以使用 Perl 编写 Apache 模块。此外，服务器中嵌入的持久解释器避免了启动外部解释器的开销和 Perl 启动时间的惩罚。

可以通过 [www/mod\_perl2](https://cgit.freebsd.org/ports/tree/www/mod_perl2/) 软件包和 Ports 安装 **mod\_perl**。有关使用此模块的文档可以在 <http://perl.apache.org/docs/2.0/index.html> 找到。

### 32.9.3.3. **mod\_php**

*PHP: Hypertext Preprocessor*（PHP）是一种通用的脚本语言，特别适合用于 Web 开发。它可以嵌入到 HTML 中，其语法借鉴了 C、Java™ 和 Perl，旨在帮助 Web 开发人员快速编写动态生成的网页。

可以通过安装相应的 Port 为 Apache 提供对 PHP 及其编写的任何其他功能的支持。

对于所有支持的版本，可以使用 `pkg` 搜索包数据库：

```sh
# pkg search php
```

将显示一个列表，包括版本和它们提供的附加功能。这些组件是完全模块化的，意味着通过安装相应的 Port 来启用功能。要为 Apache 安装 PHP 7.4，请执行以下命令：

```sh
# pkg install mod_php74
```

如果需要安装任何依赖包，它们也将被安装。

默认情况下，PHP 不会启用。需要在 **/usr/local/etc/apache24** 中的 Apache 配置文件中添加以下行以使其生效：

```ini
<FilesMatch "\.php$">
    SetHandler application/x-httpd-php
</FilesMatch>
<FilesMatch "\.phps$">
    SetHandler application/x-httpd-php-source
</FilesMatch>
```

此外，还需要更新配置文件中的 `DirectoryIndex`，并且 Apache 需要重启或重新加载以使更改生效。

通过 `pkg` 安装许多 PHP 功能的支持。例如，要安装对 XML 或 SSL 的支持，请安装各自的 Port：

```sh
# pkg install php74-xml php74-openssl
```

与以前一样，安装模块后，Apache 配置需要重新加载才能使更改生效。

要进行平滑重启以重新加载配置，执行以下命令：

```sh
# apachectl graceful
```

安装完成后，有两种方法可以获取已安装的 PHP 支持模块及构建的环境信息。第一种是安装完整的 PHP 二进制文件并运行以下命令获取信息：

```sh
# pkg install php74
```

```sh
# php -i | less
```

需要将输出传递给分页器，如 `more` 或 `less`，以便更容易处理大量输出。

最后，要更改 PHP 的全局配置，可以编辑安装在 **/usr/local/etc/php.ini** 中的文档化文件。安装时此文件不会存在，因为有两个版本可供选择，一个是 **php.ini-development**，另一个是 **php.ini-production**。这两个文件是管理员部署时的起点。

### 32.9.3.4. HTTP2 支持

Apache 默认支持 HTTP2 协议，当使用 `pkg` 安装 Port 时，会自动包含此支持。新版本的 HTTP 比较旧版本有很多改进，包括使用单一连接来访问网站，减少了 TCP 连接的往返次数。此外，包头数据也被压缩，并且 HTTP2 默认要求加密。

当 Apache 配置为仅使用 HTTP2 时，Web 浏览器将要求使用安全的加密 HTTPS 连接。当 Apache 配置为同时使用两种版本时，如果在连接过程中出现问题，则 HTTP1.1 会作为回退选项。

虽然此更改确实要求管理员进行一些修改，但它们是积极的，意味着互联网变得更加安全。此更改仅对尚未实施 SSL 和 TLS 的站点要求进行修改。

> **注意**
>
> 此配置依赖于之前的部分内容，包括 TLS 支持。建议在继续此配置之前，先完成那些指示。

首先，通过取消注释 **/usr/local/etc/apache24/httpd.conf** 中的行来启用 http2 模块，并将 mpm\_prefork 模块替换为 mpm\_event，因为前者不支持 HTTP2。

```ini
LoadModule http2_module libexec/apache24/mod_http2.so
LoadModule mpm_event_module libexec/apache24/mod_mpm_event.so
```

> **注意**
>
> 还有一个独立的 Port **mod\_http2** 可用。它旨在比捆绑在 Port **apache24** 中的模块更快地提供安全性和错误修复。虽然它不是 HTTP2 支持所必需的，但它是可用的。如果安装了该模块，应在 Apache 配置中使用 **mod\_h2.so** 替代 **mod\_http2.so**。

有两种方法可以在 Apache 中实现 HTTP2；一种方法是对所有站点和系统上运行的每个虚拟主机全局启用 HTTP2。要全局启用 HTTP2，可以在 `ServerName` 指令下添加以下行：

```sh
Protocols h2 http/1.1
```

> **注意**
>
> 要启用无加密的 HTTP2，请在 **httpd.conf** 中使用 h2h2chttp/1.1。

使用 h2c 允许在系统上传递无加密的 HTTP2 数据，但不推荐这样做。此外，使用 http/1.1 使系统可以回退到 HTTP1.1 协议版本（如果需要的话）。

要为单独的虚拟主机启用 HTTP2，请在 **httpd.conf** 或 **httpd-ssl.conf** 中的 VirtualHost 指令中添加相同的行。

通过使用 `apachectl` reload 命令重新加载配置，并在访问其中一个托管页面后使用以下方法测试配置：

```sh
# grep "HTTP/2.0" /var/log/httpd-access.log
```

这将返回类似以下内容的信息：

```sh
192.168.1.205 - - [18/Oct/2020:18:34:36 -0400] "GET / HTTP/2.0" 304 -
192.0.2.205 - - [18/Oct/2020:19:19:57 -0400] "GET / HTTP/2.0" 304 -
192.0.0.205 - - [18/Oct/2020:19:20:52 -0400] "GET / HTTP/2.0" 304 -
192.0.2.205 - - [18/Oct/2020:19:23:10 -0400] "GET / HTTP/2.0" 304 -
```

另一种方法是使用 Web 浏览器内建的站点调试工具或 `tcpdump`；不过，使用这两种方法超出了本文的范围。

通过使用 **mod\_proxy\_http2.so** 模块，可以支持 HTTP2 反向代理连接。在配置 `ProxyPass` 或 `RewriteRules` 语句时，应使用 `h2://` 作为连接方式。

## 32.9.4. 动态网站

除了 mod\_perl 和 mod\_php 外，还有其他语言可以用来创建动态网页内容。这些包括 Django 和 Ruby on Rails。

### 32.9.4.1. Django

Django 是一个 BSD 许可的框架，旨在帮助开发人员快速编写高性能、优雅的 Web 应用程序。它提供了一个对象关系映射器（ORM），使数据类型可以作为 Python 对象进行开发。对于这些对象，Django 提供了丰富的动态数据库访问 API，开发人员无需编写 SQL 代码。它还提供了一个可扩展的模板系统，使应用程序的逻辑与 HTML 展示分离。

Django 依赖于 **mod\_python** 和 SQL 数据库引擎。在 FreeBSD 中，[www/py-django](https://cgit.freebsd.org/ports/tree/www/py-django/) Port 会自动安装 **mod\_python**，并支持 PostgreSQL、MySQL 或 SQLite 数据库，默认使用 SQLite。如果要更改数据库引擎，可以在 **/usr/ports/www/py-django** 中键入 `make config`，然后安装 Port。

Django 安装完成后，应用程序需要一个项目目录以及 Apache 配置，以便使用嵌入的 Python 解释器。该解释器用于根据网站上的特定 URL 调用应用程序。

要配置 Apache 以将特定 URL 的请求传递给 Web 应用程序，请在 **httpd.conf** 中添加以下内容，指定项目目录的完整路径：

```ini
<Location "/">
    SetHandler python-program
    PythonPath "['/dir/to/the/django/packages/'] + sys.path"
    PythonHandler django.core.handlers.modpython
    SetEnv DJANGO_SETTINGS_MODULE mysite.settings
    PythonAutoReload On
    PythonDebug On
</Location>
```

有关如何使用 Django 的更多信息，请参阅 [https://docs.djangoproject.com](https://docs.djangoproject.com/)。

### 32.9.4.2. Ruby on Rails

Ruby on Rails 是另一个开源 Web 框架，提供了完整的开发堆栈。它优化了 Web 开发人员的生产力，使他们能够快速编写强大的应用程序。在 FreeBSD 上，可以使用 [www/rubygem-rails](https://cgit.freebsd.org/ports/tree/www/rubygem-rails/) 软件包和 Ports 安装。

有关如何使用 Ruby on Rails 的更多信息，请参阅 [http://guides.rubyonrails.org](http://guides.rubyonrails.org/)。
