# Apache HTTP Server (简体中文)

Related articles

- PHP
- MySQL
- PhpMyAdmin
- Adminer
- Xampp
- mod_perl

翻译状态： 本文是英文页面 Apache_HTTP_Server 的翻译，最后翻译时间：2016-06-15，点击这里可以查看翻译后英文页面的改动。

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/ 会显示一个简单的索引页面。

### 高级选项

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

    User http

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

    Listen 80

  Apach 监听的端口，要被外网访问，请在路由器开放此端口。
  如果是本地调试用，可以用下面命令设置为仅供本地访问 `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 文档.

Tip: 可以用 `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，请注意某些版本和实现 依然 有安全漏洞. 访问 http://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` 指向对应的文件。

重启 `httpd.service`.

Tip: 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

Note: -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

Note: openssl 手册 和 opnssl 文档 包含了更多信息。

### Virtual Hosts

Note: You will need to add a separate <VirtualHost dommainame:443> section for virtual host SSL support. See #Managing many virtual hosts[broken link: invalid section] 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 domainname1.dom: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 domainname1.dom:443>
        ServerAdmin webmaster@domainname1.dom
        DocumentRoot "/home/user/http/domainname1.dom"
        ServerName domainname1.dom:443
        ServerAlias domainname1.dom:443
        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>

        SSLEngine on
        SSLCertificateFile "/etc/httpd/conf/apache.crt"
        SSLCertificateKeyFile "/etc/httpd/conf/apache.key"
    </VirtualHost>

## 扩展

### PHP

首先，安装 软件包 php 和 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

另一种选择, 你可以使用`mod_proxy_fcgi` ( 使用php-fpm和mod_proxy_fcgi

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

- 将这一行放在`LoadModule`列表中 `LoadModule dir_module modules/mod_dir.so` 之后的任意地方：

     LoadModule php7_module modules/libphp7.so

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

     Include conf/extra/php7_module.conf

重启 `httpd.service`。

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

    <?php phpinfo(); ?>

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

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

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

安装 软件包 mod_fcgid 和 php-cgi.

创建目录并建立 PHP 软链接:

    # mkdir /srv/http/fcgid-bin
    # ln -s /usr/bin/php-cgi /srv/http/fcgid-bin/php-fcgid-wrapper

取消`/etc/conf.d/apache`中如下行的注释：

    HTTPD=/usr/sbin/httpd.worker

创建 `/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`，加入：

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

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

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

重启 `httpd.service`.

### MariaDB

按照PHP#MySQL/MariaDB 配置 MySQL/MariaDB。

完成后 重启 `httpd.service` 服务。

### HTTP2

要启用 http2，安装 nghttp2 软件包。然后取消 `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

### 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 官方网站
- 生成ssh_test_certificate的教程
- Apache故障排除Wiki

Category:

- Web server (简体中文)

Hidden categories:

- Pages or sections flagged with Template:Accuracy
- Pages with broken section links