建置 WordPress MU 多子網域 HTTPS for CentOS 7 + NGINX + PHP 7

WordPress.ORG

如何建置 HTTPS 的 WordPress MU 多子網域,逹到多網址多網站功能,本教學從零開始在剛安裝好的 CentOS 7,從系統基本環境、NGINX、PHP 7 的設置,到最終的 WordPress。

WordPress Multi User (簡稱為 WPMU) 多用戶,一但建置完成即可從 WordPress 後台直接新增多個「子網域」或「子目錄」方式的全新網站,好處是能共享資源 (如外掛) 以便管理。

CentOS

這裡從 CentOS 7 "最小型安裝" 的初始環境開始,須先自行完成系統安裝。

環境設定

hostname (主機名稱) 設定:

  • hostnamectl set-hostname ...:設定 hostname。
  • logout:登出。
  • hostname:顯示當前 hostname。
hostnamectl set-hostname smalljacky.com
logout

login as: root
root@61.216.xxx.xxx's password: **********
Last login: Sat Jan 20 09:29:43 2018 from 61.216.xxx.xxx

hostname
smalljacky.com

網路設定:

  • nmcli connection show:查詢網路卡裝置。
  • nmcli connection modify ...:設置 "固定 IP" 網路環境。
  • nmcli connection up  ...:啟用網路。
nmcli connection show
NAME  UUID                                  TYPE            DEVICE
eth0  155337be-567d-4667-82b7-ae1d9f6e722c  802-3-ethernet

nmcli connection modify eth0 connection.autoconnect yes ipv4.address "61.216.xxx.xxx/24" ipv4.gateway "61.216.xxx.xxx" ipv4.dns 168.95.1.1 ipv4.method manual
nmcli connection up eth0

安裝後續須用軟體:

  • bash-completion:Bash  shell 指令自動補齊,透過雙擊鍵盤 Tab
  • wget:支持通過 HTTP、HTTPS 和 FTP 下載檔案。
  • yum-utils:包含了一些在預設中未被啟用的 yum 插件。
yum install bash-completion wget yum-utils

免費萬用字元憑證

使用萬用字元憑證 (Wildcard Certificates),即可通用於所有子網域的網站,這裡使用  Let’s Encrypt 的免費萬用字元憑證,申請步驟請參考 Let’s Encrypt 免費 Wildcard 萬用字元憑證 SSL/TLS for CentOS 7

NGINX

安裝

CentOS 7 中,NGINX 並未被正式收錄在 yum,因此須自行加入 NGINX 官方提供的 CentOS 7 yum repository,即可直接安裝。

rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
yum install nginx

修改網站根目錄的擁有者、群組為 NGINX:

chown -R nginx:nginx /usr/share/nginx/html/

虛擬主機設定檔

開啟 NGINX 預設的主機設定檔,針對 WordPress MU (多站點、子網站) 子網域和 HTTPS 設定。

參數 server_name:

  • smalljacky.com 為主網站。
  • *.smalljacky.com 為 WordPress MU (多站點、子網站) 子網域。

參數 root:

  • 網站根目錄。
cp /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bak
vi /etc/nginx/conf.d/default.conf
map $http_host $blogid {
    default       -999;

    #Ref: http://wordpress.org/extend/plugins/nginx-helper/
    #include /var/www/wordpress/wp-content/plugins/nginx-helper/map.conf;
}

# 將 http 301 永久轉跳至 https
server {
        listen 80;
        listen [::]:80;
        server_name smalljacky.com *.smalljacky.com;
        return 301 https://$server_name$request_uri;
}

server {
    # 使用 https 和 http/2 協定
    listen 443 ssl http2;
    # 上述的 IPv6 方式
    listen [::]:443 ssl http2;

    server_name smalljacky.com *.smalljacky.com;


    # 瀏覽器 Cache 期限 (1M = 1 Month)
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff)$ {
        expires 1M;
    }


    root /usr/share/nginx/html;
    index index.php;

    #
    # certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
    #

    # SSL 憑證證書路徑
    ssl_certificate /etc/letsencrypt/live/smalljacky.com-0001/fullchain.pem;
    # 私鑰路徑
    ssl_certificate_key /etc/letsencrypt/live/smalljacky.com-0001/privkey.pem;
    # 緩存有效期
    ssl_session_timeout 1d;
    # 緩存憑證類型和大小
    ssl_session_cache shared:SSL:50m;


    #
    # intermediate configuration. tweak to your needs.
    #

    # 使用的加密協定
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    # 加密演算法,越前面的優先級越高
    ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
    # 交握過程使用 Server 的首選加演算法,這裡使用 Client 為首選
    ssl_prefer_server_ciphers on;


    #
    # HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
    #

    # 增加 http header
    add_header Strict-Transport-Security max-age=15768000;


    location / {
        try_files $uri $uri/ /index.php?$args ;
    }

    location ~ \.php$ {
        try_files $uri = 404;
        fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    #WPMU Files
    location ~ ^/files/(.*)$ {
        try_files /wp-content/blogs.dir/$blogid/$uri /wp-includes/ms-files.php?file=$1;
        access_log off;
        log_not_found off;
        expires max;
    }

    #WPMU x-sendfile to avoid php readfile()
    location ^~ /blogs.dir {
        internal;
        alias /usr/share/nginx/html/wp-content/blogs.dir;
        access_log off;
        log_not_found off;
        expires max;
    }

    #add some rules for static content expiry-headers here
}

服務設定

啟用服務並開機自動啟用:

systemctl start nginx
systemctl enable nginx

Firewall (防火牆) 設定

查看 Firewall 針對當前網路裝置的設定:

firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources:
  services: ssh dhcpv6-client
  
# ... 以下省略 ..

刪除 Firewall 預設的 Services:

firewall-cmd --permanent --remove-service={ssh,dhcpv6-client}
success

設定 Firewall 僅允許哪些 IP 才能使用哪些 Services:

  • ssh:透過該通道與 Server 建立連線。
  • samba:File Server (檔案伺服器)。(為了撰寫程式的效率,小傑都透過此方式掛載 Web Server 的根目錄來撰寫程式)
firewall-cmd --permanent --zone=public --add-rich-rule="rule family='ipv4' source address='61.216.xxx.xxx/32' service name='ssh' accept"
success
 
firewall-cmd --permanent --zone=public --add-rich-rule="rule family='ipv4' source address='61.216.xxx.xxx/32' service name='samba' accept"
success

設定 Firewall 允許 http (80 Port) 與 https (443 Port) 封包通行:

[root@smalljacky ~]# firewall-cmd --permanent --zone=public --add-service={http,https}
success

重新載入 Firewall 設定:

firewall-cmd --reload
success

檢查 Firewall 設定:

firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources:
  services: http https
  
# ... 中間省略 ...

  rich rules:
        rule family="ipv4" source address="61.216.xxx.xxx/32" service name="ssh" accept
        rule family="ipv4" source address="61.216.xxx.xxx/32" service name="samba" accept

啟用 Gzip 壓縮

有人訪問網站時,伺服器會傳送相關檔案給瀏覽器,當傳送的檔案越大,所花費的時間就會越長,也就表示網頁開啟的速度就越慢,因此可先將檔案進行 Gzip 壓縮後在進行傳送給瀏覽器,將可有效減少傳輸的時間。

開啟 nginx.conf 進行設定:

vi /etc/nginx/nginx.conf
http {

# ... 以上省略 ...

    # 啟用 gzip (預設為註解,也就是未啟用)
    gzip on;
    # 多小的檔案容量不進行 gzip 壓縮
    gzip_min_length 1k;
    # 壓縮緩衝區的的 number size
    gzip_buffers 4 16k;
    # 壓縮比例 1-9,數值越高壓縮越好 (也就是檔案越小),但系統處理速度越慢
    gzip_comp_level 5;
    # 要壓縮的檔案類型
    gzip_types text/plain application/javascript application/json  text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
    # 是否在 http header 加入 Vary: Accept-Encoding,通知瀏覽器有使用 Gzip 壓縮
    gzip_vary on;

# ... 以下省略 ...
}

重新載入 NGINX 設定檔:

systemctl reload nginx

PHP

安裝

請參考 CentOS 7 安裝 PHP 7.x

PHP-FPM

安裝:

yum install php-fpm

先備存 PHP-FPM 設定檔後在進行設定:

cp /etc/php-fpm.d/www.conf /etc/php-fpm.d/www.conf.bak
vi /etc/php-fpm.d/www.conf

;listen = 127.0.0.1:9000
listen = /var/run/php-fpm/php-fpm.sock

;user = apache
user = nginx

;group = apache
group = nginx

; 預設帳戶、群組,為正在運作的帳戶
;listen.owner = nobody
;listen.group = nobody
listen.owner = nginx
listen.group = nginx

; 權限(預設為 0666)
;listen.mode = 0666

; session 的路徑
php_value[session.save_path] = /var/lib/php/session

修改 session 路徑的擁有者、群組為 NGINX:

chown nginx:nginx /var/lib/php/session/

服務設定

啟用 PHP-FPM 服務並開機自動啟用:

systemctl start php-fpm
systemctl enable php-fpm

重啟 NGINX 服務:

systemctl restart nginx

網站緩慢優化

如果遇到網站使用一段時間後越來越緩慢,而只要重新開機或重啟 NGINX 與 PHP-FPM 就又恢復正常,那就有可能是 PHP-FPM 預設連線數設定太高所導致的,如下查看記憶體使用狀況:(詳細說明可參考鳥哥的 Linux 私房菜 -- 第十六章、程序管理與 SELinux 初探)

free -m
              total        used        free      shared  buff/cache   available
Mem:            992         131         713           6         146         701
Swap:          1906           0        1906

可依伺服器效能自行調整 PHP-FPM 設定檔:

vi /etc/php-fpm.d/www.conf

# ... 以上省略 ...

# 如何控制子程序,值有 static (Web 專用 Server 設定它即可) 和 dynamic (預設值)。
# 設定值為 static 則由 pm.max_children 指定固定的子程序數量;值為 dynamic 則由下列參數設定決定。
pm = dynamic

# 子程序最大數
pm.max_children = 7

# 啟動時的程序數量
pm.start_servers = 2

# 空閒時程序最小值,如果空閒程序小於設定值,則建立新的子程序。
pm.min_spare_servers = 1

# 空閒程序最大值,如果空閒程序大於設定值,進行清理。
pm.max_spare_servers = 3

# ... 以下省略 ...

重新載入 PHP-FPM 設定檔:

systemctl reload php-fpm

SELinux 安全性限制

上傳檔案失敗 / 更新無法建立目錄

查看網站根目錄預設的文件類型為 httpd_sys_content_t:

ll -dZ /usr/share/nginx/html
drwxr-xr-x. nginx nginx system_u:object_r:httpd_sys_content_t:s0 /usr/share/nginx/html

使用遞迴來讓所有的目錄加入 SELinux 的 httpd_sys_rw_content_t 文件類型:

chcon -R -t httpd_sys_rw_content_t /usr/share/nginx/html

檢查 SELinux 設定:

ll -dZ /usr/share/nginx/html
drwxr-xr-x. nginx nginx unconfined_u:object_r:httpd_sys_rw_content_t:s0 /usr/share/nginx/html

無法網路連結 DataBase

設定 SELinux httpd_can_network_connect_db 允許網路連結 DataBase:

setsebool -P httpd_can_network_connect_db=1

無法發送 Email

訪客在文章留言後,WordPress 會自動寄發 Email 至管理員信箱,如一直無法收到信,請先查詢 maillog 的資訊,如下表示權限被拒:

vi /var/log/maillog

Feb 22 22:46:05 smalljacky postfix/sendmail[16892]: fatal: open /etc/postfix/main.cf: Permission denied

檢查允許透過 PHP 寄信的 SELinux httpd_can_sendmail 狀態,如下則不允許:

getsebool -a | grep httpd_can_sendmail
httpd_can_sendmail --> off

設定 SELinux httpd_can_sendmail 允許透過 PHP 寄信:

setsebool -P httpd_can_sendmail=1

WordPress

下載

  1. 至 WordPress 官網下載軟體壓縮檔。
  2. 開啟壓縮檔,將 wordpress 目錄下 (不含 wordpress 目錄) 所有檔案移至網站根目錄 。
  3. 將 WordPress 的設定檔案 wp-config-sample.php 另存為 wp-config.php。

設定

編輯 WordPress 設定檔 wp-config.php (僅列出修改部份):

  • MySQL DataBase:填入對應的資訊。
  • 認證唯一金鑰設定:開啟私密金鑰服務,並將自動產生的字串符號貼上取代原設定。
  • WordPress 資料表前綴:增加安全性。
  • 啟用多網誌站台與網誌網路功能:取消註解符號 //,並將參數改為 true。
vi /usr/share/nginx/html/wp-config.php
<?php

// ... 以上省略 ...

// ** MySQL 設定 - 您可以從主機服務提供商獲取相關資訊。 ** //
/** WordPress 的資料庫名稱,請更改 "database_name_here" */
define('DB_NAME', 'database_name_here');

/** MySQL 資料庫使用者名稱,請更改 "username_here" */
define('DB_USER', 'username_here');

/** MySQL 資料庫密碼,請更改 "password_here" */
define('DB_PASSWORD', 'password_here');

/** MySQL 主機位址 */
define('DB_HOST', 'localhost');

/** 建立資料表時預設的文字編碼 */
define('DB_CHARSET', 'utf8');

/** 資料庫對照型態。如果不確定請勿更改。 */
define('DB_COLLATE', 'utf8_unicode_ci');

/**#@+
 * 認證唯一金鑰設定。
 *
 * 將這些更改為不同的唯一字串或符號。
 * 您可以使用 {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org 私密金鑰服務} 來自動產生。
 * 您可於任何時候修改這些字串讓 Cookies 失效。這將會強制所有使用者必須重新登入。
 *
 * @since 2.6.0
 */
define('AUTH_KEY',         'put your unique phrase here');
define('SECURE_AUTH_KEY',  'put your unique phrase here');
define('LOGGED_IN_KEY',    'put your unique phrase here');
define('NONCE_KEY',        'put your unique phrase here');
define('AUTH_SALT',        'put your unique phrase here');
define('SECURE_AUTH_SALT', 'put your unique phrase here');
define('LOGGED_IN_SALT',   'put your unique phrase here');
define('NONCE_SALT',       'put your unique phrase here');

/**#@-*/

/**
 * WordPress 資料表前綴。
 *
 * 若您為每個 WordPress 設定不同的資料表前綴,則可在同個資料庫內安裝多個 WordPress。
 * 前綴只能使用半型數字、字母和底線!
 */
$table_prefix  = 'wp_';

// ... 中間省略 ...

/**
 * 啟用多網誌站台與網誌網路功能
 *
 * 若 WP_ALLOW_MULTISITE 值為 true 可啟用多網誌站台功能。
 */
define('WP_ALLOW_MULTISITE', true);

// ... 以下省略 ...config.php

安裝

開啟 Browser 輸入 [網址]/wp-admin/install.php (小傑的為 smalljacky.com/wp-admin/install.php),依步驟安裝完成後登入後台。

進入工具 > 網誌網路安裝 > 選取 子網域 > 點擊安裝。

複製 1. 新增以下程式碼至 /usr/share/nginx/html/ 的 wp-config.php 檔案… (請務必貼至 啟用多網誌站台與網誌網路功能 的下面)。

vi /usr/share/nginx/html/wp-config.php
<?php

// ... 以上省略 ...

/**
 * 啟用多網誌站台與網誌網路功能
 *
 * 若 WP_ALLOW_MULTISITE 值為 true 可啟用多網誌站台功能。
 */
define('WP_ALLOW_MULTISITE', true);

/**
 * 啟用網誌網路站台的功能。
 */
define('MULTISITE', true);
define('SUBDOMAIN_INSTALL', true);
define('DOMAIN_CURRENT_SITE', 'smalljacky.com');
define('PATH_CURRENT_SITE', '/');
define('SITE_ID_CURRENT_SITE', 1);
define('BLOG_ID_CURRENT_SITE', 1);

// ... 以下省略 ...

點擊下方的登入,正確完成後就會發現後台介面有一些改變。

新增新網誌 (子網域網站):點擊最上面我的網站 > 網站 > 新增。

其它設定

最大上傳檔案大小

修改 NGINX 和 PHP 設定檔來調整上傳容量限制 (以上傳容量調至 200M 為例)。

NGINX 設定:

vi /etc/nginx/conf.d/default.conf
# ... 以上省略 ...

server {
    # 使用 https 和 http/2 協定
    listen 443 ssl http2;
    # 上述的 IPv6 方式
    listen [::]:443 ssl http2;

    server_name smalljacky.com *.smalljacky.com;


    #
    # 上傳檔案相關設定
    #

    # 上傳檔案允許容量
    client_max_body_size 200M;

    client_header_timeout 600s;
    client_body_timeout 600s;

    # fastcgi 為使用本機的 php-fpm,如果是透過 proxy 則前綴要改成 proxy_
    fastcgi_connect_timeout 600s;
    fastcgi_read_timeout 600s;
    fastcgi_send_timeout 600s;

# ... 以下省略 ...

PHP 設定 (僅列出須修改部份):

vi /etc/php.ini
 
upload_max_filesize = 200M
post_max_size = 200M
max_execution_time = 300
max_input_time = 600

後台調整設定:

上傳檔案型態

依需求調整允許上傳的副檔名:

參考

在〈建置 WordPress MU 多子網域 HTTPS for CentOS 7 + NGINX + PHP 7〉中有 1 則留言

發表留言