Apache HTTP Server (简体中文) - ArchWiki

Jump to content

# Apache HTTP Server (简体中文)

From ArchWiki

相关文章

- PHP
- MySQL
- PhpMyAdmin
- Adminer
- XAMPP
- mod_perl

翻译状态：本文是 Apache_HTTP_Server 的翻译。上次翻译日期：2017-12-04。如果英文版本有所更改，则您可以帮助同步翻译。

LAMP是指在许多web 服务器上使用的一个软件组合：Linux,Apache,MySQL/MariaDB以及PHP。

Apache HTTP 服务器，简称 Apache，是非常流行的Web服务器软件。通常和脚本语言比如 PHP，数据库 MySQL 一起工作，合称为 LAMP 栈(Linux, Apache, MySQL, PHP). 本文介绍。本文档描述了怎样安装设置 Apache 网页服务器。以及选择安装 PHP和 MySQL 并集成到Apache服务器中。

## 安装

安装 软件包 apache.

## 配置

Apache 配置文件位于 `/etc/httpd/conf`，主要的配置文件是 `/etc/httpd/conf/httpd.conf`, 此文件会引用其它文件。

用默认配置可以启动一个简单的服务，有用户访问时会提供目录 `/srv/http` 下的内容。

启动 `httpd.service` systemd 服务，Apache 就会启动，从浏览器中访问 http://localhost/ 会显示一个简单的索引页面。

### 高级选项

请参考 Apache 完整 directives 配置选项 和 directive 快速参考.

请关注一下 `/etc/httpd/conf/httpd.conf` 中的下面选项:

    User http

  出于安全原因，Apache以root用户身份启动(直接的或者通过启动脚本)后将立即切换为 `/etc/httpd/conf/httpd.conf`中指定的 UID，默认配置是 http, 安装时会自动创建此用户。

    Listen 80

  Apache 监听的端口，要被外网访问，请在路由器开放此端口。
  如果是本地调试用，可以用下面命令设置为仅供本地访问 `Listen 127.0.0.1:80`.

    ServerAdmin you@example.com

  管理员的电子邮件，在错误页面会展示给用户。

    DocumentRoot "/srv/http"

  网页的目录.
  如果需要可以修改这个目录，请记得同步修改 `<Directory "/srv/http">` 和`DocumentRoot`,否则访问新位置时可能出现 403 Error (缺少权限)问题。不要忘记修改 `Require all denied` 行到 `Require all granted`，否则会出现 403 Error. DocumentRoot 目录及其父目录必须有可执行权限，这样再能被服务器进程使用的用户访问到(用 `chmod o+x /path/to/DocumentRoot` 设置)，否则会出现 403 Error.

    AllowOverride None

  在 `<Directory>` 段落中的这个设置会让 Apache 完全忽略 `.htaccess` 文件。从 Apache 2.4，这个设置以及是默认的，所以如果要使用 `.htaccess`，请允许Overide. 如果要在 `.htaccess` 中使用 `mod_rewrite` 或其它设置, 可以指定哪些目录允许覆盖服务器配置。更多信息请访问 Apache 文档.

提示： 可以用 `apachectl configtest` 检查配置文件是否存在问题。

更多设置可以访问 `/etc/httpd/conf/extra/httpd-default.conf`，例如

关闭服务器签名:

    ServerSignature Off

隐藏 Apache 和 PHP 版本等属性:

    ServerTokens Prod

### 用户目录

在默认设置下，可以通过 http://localhost/~yourusername/ 访问用户的主目录并显示 `~/public_html` 中的内容 (可以通过 `/etc/httpd/conf/extra/httpd-userdir.conf` 设置). 要禁用这个访问，请注释掉 `/etc/httpd/conf/httpd.conf` 文件中的如下行：

    Include conf/extra/httpd-userdir.conf

The factual accuracy of this article or section is disputed.

Reason: It is not necessary to set `+x` for every users, setting it only for the webserver via ACLs suffices (see Access Control Lists#Granting execution permissions for private files to a Web Server). (Discuss in Talk:Apache HTTP Server (简体中文))

请正确设置目录的权限，使得 Apache 可以访问到文件。主目录和 `~/public_html` 必须是可被其它用户执行:

    $ chmod o+x ~
    $ chmod o+x ~/public_html
    $ chmod -R o+r ~/public_html

重启 `httpd.service` 服务以应用更改。参考 Umask#Set the mask value.

### TLS/SSL

警告： 如果计划使用 SSL/TLS，请注意某些版本和实现 依然 有安全漏洞. 访问 https://disablessl3.com/ 和 https://weakdh.org/sysadmin.html 可以查看当前的安全漏洞和服务器处理方式。

OpenSSL 提供了 TLS/SSL 支持，默认已经安装在 Arch 中。

在 `/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

TLS/SSL 需要密钥和认证，如果你有公开域名，可以使用 Let's Encrypt 免费获取认证，如果没有，请参考 #创建密钥并自签名.

获取密钥和认证之后，请将 `/etc/httpd/conf/extra/httpd-ssl.conf` 中的 `SSLCertificateFile` 和 `SSLCertificateKeyFile` 指向对应的文件。如果还生成了 CA 认证链，请将文件名设置到 `SSLCertificateChainFile`.

重启 `httpd.service`.

提示： Mozilla 的 SSL/TLS 文章 包含了 Apache 相关 配置的指南和一个 自动生成工具，可以有助于创建更安全的配置。

#### 创建密钥并自签名

创建一个私钥并自己签名认证，对于不需要 CSR 的大部分使用来说已经足够:

    # cd /etc/httpd/conf
    # openssl req -new -x509 -nodes -newkey rsa:4096 -keyout server.key -out server.crt -days 1095
    # chmod 400 server.key

注意： -days 参数是可选的，RSA 密钥大小最低是 2048 (default).

如果需要创建 CSR，用下面的密钥创建方:

    # openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out server.key
    # chmod 400 server.key
    # openssl req -new -sha256 -key server.key -out server.csr
    # openssl x509 -req -days 1095 -in server.csr -signkey server.key -out server.crt

注意： openssl 手册 和 opnssl 文档 包含了更多信息。

### Virtual Hosts

注意： You will need to add a separate <VirtualHost *:443> section for virtual host SSL support. See #管理多个主机 for an example file.

如果需要不止一个主机，取消 `/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/apache.crt"
        SSLCertificateKeyFile "/etc/httpd/conf/apache.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 页面，完成 PHP 的安装。

有多种方式可以在 Apache 下使用 PHP，#使用 libphp 最简单，但是扩展性最差，libphp 还需要修改 mpm 模块，可能影响其它扩展，比如和 #HTTP2 不兼容。

#### 使用 libphp

安装软件包 php-apache。

php-apache 中包含的 `libphp7.so` 不支持 `mod_mpm_event`，仅支持 `mod_mpm_prefork`(FS#39218)。需要在 `/etc/httpd/conf/httpd.conf` 中注释掉:

    #LoadModule mpm_event_module modules/mod_mpm_event.so

取消下面行的注释:

    LoadModule mpm_prefork_module modules/mod_mpm_prefork.so

不然将发生下面的错误:

    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

另外在本小节的下方还有两种处理高并发的方案供选择． 　 ( 使用php-fpm管理进程 和使用mod_fcgid管理进程)

要启用 PHP，在 `/etc/httpd/conf/httpd.conf` 中添加如下行：

- 将这一行放在`LoadModule` 的末尾：

     LoadModule php7_module modules/libphp7.so
     AddHandler php7-script php

- 将这一行放到`Include`列表的末尾：

     Include conf/extra/php7_module.conf

重启 `httpd.service`。

#### 使用 php-fpm 和 mod_proxy_fcgi

这种方式是使用php-fpm来管理进程的，进程不是由apache启动和管理的．

注意： 与使用ProxyPass的广泛设置不同，使用SetHandler的代理配置遵守Apache指令，例如DirectoryIndex。 这是为了确保与为libphp7、mod_fastcgi和mod_fcgid而设计的软件有更好的兼容性。 如果您仍然想尝试使用ProxyPass，请尝试使用如下所示的行：

    ProxyPassMatch ^/(.*\.php(/.*)?)$ unix:/run/php-fpm/php-fpm.sock|fcgi://localhost/srv/http/$1

安装 官方软件包 php-fpm .

启用代理模块:

    /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` 写入以下内容:

    /etc/httpd/conf/extra/php-fpm.conf

    DirectoryIndex index.php index.html
    <FilesMatch \.php$>
        SetHandler "proxy:unix:/run/php-fpm/php-fpm.sock|fcgi://localhost/"
    </FilesMatch>

把以下这句添加到配置文件 `/etc/httpd/conf/httpd.conf` 中 include 部份的最后

    Include conf/extra/php-fpm.conf

注意： 在 `sock` 和 `fcgi` 中间的管道符两边不要有空格! `localhost` 可以替换成任何的字符串. 详细请见 here

你可以自行配置 PHP-FPM 通过这个编辑这个配置文件 `/etc/php/php-fpm.d/www.conf`, 但是默认的配置已经工作的很好了.

重启 `httpd.service` 和 `php-fpm.service`这两个服务.

注意： 如果之前在 `httpd.conf` 加入了下面内容，请删除它们，已经不再需要：

    LoadModule php7_module modules/libphp7.so
    Include conf/extra/php7_module.conf

#### 使用 apache2-mpm-worker 和 mod_fcgid

这种方式和上一种方式(php-fpm)的区别：

       php-fgi进程是由apache模块启动并管理，而不需要配置和使用php-fpm来管理进程。
       在php-cgi进程以apache用户身份运行，php程序写的文件，其权限为apache用户（而不像php-fpm下写文件为php-fpm用户所有，默认是nobody），这样在目录权限管理方面一致性高些。

安装 软件包 mod_fcgid(详情)和 php-cgi。

创建需要的目录并建立软链接:

    # 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

并添加如下配置:

    LoadModule fcgid_module modules/mod_fcgid.so
    Include conf/extra/httpd-mpm.conf
    Include conf/extra/php-fcgid.conf

Restart `httpd.service`.

#### 测试 PHP

在 apache 文档根目录（即`/srv/http/`或`~public_html`）中创建test.php文件，在其中写入：

    <?php phpinfo(); ?>

然后访问： http://localhost/test.php 或者 http://localhost/~myname/test.php

高级的配置和扩展，请设置 PHP.

### HTTP2

要启用 http2，安装 libnghttp2 软件包(属于core仓库,一般默认已经安装)。然后取消 `httpd.conf` 中下面行前的注释:

    LoadModule http2_module modules/mod_http2.so

并加入:

    Protocols h2 http/1.1

更多信息请参考 mod_http2 文档。

## 问题处理

### Apache 的状态和日志

状态信息可以用 systemctl 查询。

Apache 默认的系统日志位于 `/var/log/httpd/`。

### 启动后出现 Error: PID file /run/httpd/httpd.pid not readable

在 `httpd.conf` 中注释掉 `unique_id_module` 行：

    #LoadModule unique_id_module modules/mod_unique_id.so

### AH00534: httpd: Configuration error: No MPM loaded.

最近的升级需要修改 `httpd.conf` 配置文件，取消下面行前的注释：

    /etc/httpd/conf/httpd.conf

    LoadModule mpm_prefork_module modules/mod_mpm_prefork.so

### AH00072: make_sock: could not bind to address

多种都可能导致此问题，最常见的问题是已经有程序监听了设置的端口，通过下面命令确认：

    # netstat -lnp | grep -e :80 -e :443

如该能查到结果，关闭占用端口的程序，然后重试。

还有一个原因是 Apache 没有以 root 执行，运行下面命令看看问题是否依然发生：

    # httpd -k start

最后，可能配置有问题，导致程序同时监听了端口两次，例如下面的配置就有这个问题：

    Listen 0.0.0.0:80
    Listen [::]:80

### php.ini 中的 max_execution_time 设置无效

`php.ini` 中的 `max_execution_time` 设置为大于 30 (秒), 还会受到 `503 Service Unavailable` 的话，还需要添加 `ProxyTimeout` 到 `<FilesMatch \.php$>` 段落之前:

    /etc/httpd/conf/httpd.conf

    ProxyTimeout 300

重启 `httpd.service`.

## 参阅

- Apache 官方网站
- Apache wiki
- 生成ssh_test_certificate的教程
- Apache故障排除Wiki

Category:

- Web server (简体中文)

Hidden category:

- Pages or sections flagged with Template:Accuracy