Apache HTTP 伺服器

出自 Arch Linux 中文维基

LAMP是指在許多web 伺服器上使用的一個軟體組合:Linux,Apache,MySQL/MariaDB以及PHP。

Apache HTTP 伺服器,簡稱 Apache,是非常流行的Web伺服器軟體。通常和腳本語言比如 PHP,資料庫 MySQL 一起工作,合稱為 LAMP 棧(Linux, Apache, MySQL, PHP). 本文介紹。本文檔描述了怎樣安裝設置 Apache 網頁伺服器。以及選擇安裝 PHPMySQL 併集成到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

本文或本章節的事實準確性存在爭議。

原因: 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).(在 Talk:Apache HTTP 伺服器 中討論)


請正確設置目錄的權限,使得 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 中的 SSLCertificateFileSSLCertificateKeyFile 指向對應的文件。如果還生成了 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.confInclude 單獨的配置文件:

#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
注意:sockfcgi 中間的管道符兩邊不要有空格! localhost 可以替換成任何的字符串. 詳細請見 here

你可以自行配置 PHP-FPM 通過這個編輯這個配置文件 /etc/php/php-fpm.d/www.conf, 但是默認的配置已經工作的很好了.

重啟 httpd.servicephp-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_fcgidAUR(詳情)和 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.

參閱[編輯 | 編輯原始碼]