[CentOS 7] 整合 Nginx、MariaDB、PHP 7 組成 LEMP Server

by 1月 17, 2016 27 意見        

在 Linux 的世界裡,要架 Web 站的套件組合,最常見的絕對是 LAMP = Linux + Apache + MySQL + PHP。不過,由 Linux + Nginx + MariaDB + PHP 的 LEMP 套件組合也不遑多讓,後勢看漲。
最後更新日期 - 2016/12/08

相信有些朋友應該會覺得很奇怪,既然是縮寫,那應該叫做 LNMP 才對,為什麼文章標題是用 LEMP?

反過來,先請教大家一個問題,Nginx 這個字要怎麼念?
其實這個俄羅斯來的 Web Server 念成「Engine X」,發音是 E 開頭,而 LEMP 可以組成一個能發音的詞,LNMP 不行,所以在國外都是用 LEMP 來當作簡稱。

另外,為什麼資料庫套件不用 MySQL 而是換成 MariaDB
因為 MySQL 在被併購之後,或許 Oracle 擔心影響到 Oracle Database 這個主力命脈的生意,有陣子幾乎把它打到冷宮去不聞不問,原來的專案開發成員擔心從此被放棄,甚至會變成 閉源軟體 (Close Source),乾脆重新成立一個新專案,以 100% 相容 MySQL 為標準,創造了 MariaDB 出來。

而 PHP 7 的出現,在去年也是個大新聞,這個 Web 界的程式語言新霸主終於也來到我們的面前,至於它到底進化了哪些呢?可以參閱 ITHome - 2 億網站效能救星 PHP 7 問世 系列文章的介紹。

事前準備


請參照 找不到可靠的套件來源嗎?幫 CentOS 6 加入可靠的第三方的套件庫 的內容。

加入 EPEL 套件庫
sudo yum -y install epel-release

Remi 套件庫
sudo rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm

以及 Nginx 套件庫
sudo vi /etc/yum.repos.d/nginx.repo

[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1



別忘了更新一下所有套件庫的快取資料。
sudo yum -y update


安裝主要套件


安裝的步驟也很簡單,全部交給 yum 指令來搞定就行了。
sudo yum -y install nginx php70-php-fpm mariadb-server

因為安裝的套件略多,這邊要稍等一下下 ...

對,就是這麼簡單!
如果各位勇者有興趣自己編譯的話,原始碼在這裡請自便... XD。

開始設定及實測


Nginx


先允許防火牆讓 HTTP、HTTPS 封包通過。
sudo firewall-cmd --permanent --zone=public --add-service=http
sudo firewall-cmd --permanent --zone=public --add-service=https
sudo firewall-cmd --reload

直接啟動服務,並讓它在開機後自動啟動。
sudo systemctl restart nginx
sudo systemctl enable nginx

再修改預設主站台設定檔。
sudo vi /etc/nginx/conf.d/default.conf

改成下列內容,啟用 PHP 的支援。
server {
    listen       80;
    server_name  localhost;

    charset utf-8;
    access_log  /var/log/nginx/access.log  main;

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

    location / {
        try_files $uri $uri/ =404;
    }

    error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

另外,因為 SELinux 會限制 Nginx 寫入動作,所以還要打開主目錄的存取權限。
sudo chcon -R -t httpd_sys_rw_content_t /usr/share/nginx/html

最後,讓新的設定值生效。
sudo systemctl reload nginx

在瀏覽器上就可以看到 Nginx 正常啟動了。

PHP-FPM


Nginx 跟 Apache 不同,必須配合 PHP-FPM 來啟用 PHP 的支援。

首先修改一下 PHP 的主設定檔。
sudo vi /etc/opt/remi/php70/php.ini

找到 ;cgi.fix_pathinfo=1,將 1 改成 0,並把註解拿掉。
cgi.fix_pathinfo=0

修改這個參數是因為有資安漏洞,請參閱 风雪之隅 - Nginx + PHP CGI的一个可能的安全漏洞

簡單的說,
就是因為 PHP 在解析路徑的時候,有機會被拿來執行那些偽裝成普通檔案的惡意程式碼。

接著,修改 PHP-FPM 的主設定檔。
sudo vi /etc/opt/remi/php70/php-fpm.d/www.conf

配合 Nginx 修改下列設定值。
user = nginx
group = nginx
listen.owner = nobody
listen.group = nobody

啟動 PHP-FPM,並讓它在開機後自動啟動。
sudo systemctl restart php70-php-fpm
sudo systemctl enable php70-php-fpm

測試的方法也很簡單,只要在預設站台的根目錄 /usr/share/nginx/html 下面,建立一個 PHP 檔案。
sudo vi /usr/share/nginx/html/info.php

就加入這一行指令即可。
<?php phpinfo(); ?>


不必重新啟動 Nginx 或是 PHP-FPM,直接打開瀏覽器,在網址列除了輸入 IP 之外,再加上 php 檔案名稱,例如 http://192.168.88.155/info.php,看到這個畫面就代表成功了。

MariaDB


啟動 MariaDB Server,並讓它在開機後自動啟動。
sudo systemctl restart mariadb
sudo systemctl enable mariadb

進行一些安全性的調整。
mysql_secure_installation

MariaDB 的 root 帳號,預設沒有密碼。

設定 root 帳號的新密碼,必須輸入兩次。

移除匿名帳號。

拒絕 root 帳號從遠端登入,這邊為了管理方便,所以選擇繼續允許。

刪除測試資料庫。

重新載入使用者權限。

完成之後,試著連線到 MariaDB Server,用 root 帳號的新密碼登入測試一下。
mysql -u root -p

此外,為了讓 PHP 可以連接 MariaDB,要再額外安裝 PHP 的模組。
sudo yum -y install php70-php-mysqlnd

裝好之後,重新啟動 PHP-FPM。
sudo systemctl restart php70-php-fpm

回到瀏覽器,重新載入剛剛的 PHP 測試頁,就會看到 MariaDB 的支援模組了。
(我們沒看錯,MySQL 跟 MariaDB 用同一個模組。)


碎碎念


其實我本來是先用 Webtatic 提供的 PHP 7 套件 進行實作,再三確認過設定值及操作步驟沒錯,偏偏服務起不來就是起不來,後來果斷放棄 Webtatic 改用 Remi,結果一次就成功 ... @@


參考資料


圖片來源

  • CentOS、Nginx、MariaDB、PHP 官網。

更新紀錄

  • 2016/01/18 撰文。
  • 2016/12/08 更新,加入了 SELinux 的存取權限調整,感謝 Fung Vincent 告知。

Heracles Jam,江湖人稱「海公公」

IT 技術家 - 創站部落客

一個常用 Windows、慣用 macOS、愛用 Linux 的 3C 阿宅
現職 MIS / 業界講師 / 資訊顧問 / 部落客

27 則留言 :

  1. 當然可以,
    不過目前還沒看到有好心人打包放出來,請這邊右轉到官網下載 source code,自己編譯囉 ...
    http://php.net/downloads.php

    回覆刪除
  2. 這樣還是不能用阿,NGINX還是會把PHP檔案視為一般檔案下載...

    回覆刪除
    回覆
    1. 我剛剛用了 Safari, Firefox, Chrome 來測試,沒遇到相同的問題,
      請再檢查一下 /etc/nginx/conf.d/default.conf 的 PHP 段落設定值。

      刪除
    2. 你可以檢查一下/etc/nginx/conf.d/default.conf 的 PHP 段落裡是
      location(空白鍵)~(空白鍵)\.php$(空白鍵){
      都常會少輸入了第二個空白鍵

      刪除
    3. 感恩樓上的朋友補充,這的確是常發生的事....
      (曾經為了一個空格,而失去四個小時的工程師留 @@)

      刪除
  3. 作者已經移除這則留言。

    回覆刪除
    回覆
    1. 出錯的原因, 原來只是我打錯了字~ 煩你了!

      刪除
    2. 習慣就好... (醬子好像沒有安慰到你 XDD)
      其實我也常遇到這種自己去撞牆的事,難免啦....

      刪除
  4. chcon: can't apply partial context to unlabeled file ‘index.html’
    chcon: can't apply partial context to unlabeled file ‘50x.html’
    chcon: can't apply partial context to unlabeled file ‘/usr/share/nginx/html’

    回覆刪除
    回覆
    1. 一直找不到答案 為什麼

      刪除
    2. 最後採取的方法是把SELinux disable

      刪除
    3. 文章裡的這行指令有執行嗎?
      sudo chcon -R -t httpd_sys_rw_content_t /usr/share/nginx/html

      刪除
    4. 有執行 執行之後的反饋是我上述那樣

      刪除
    5. 那你可能要查一下 SELinux Contexts 是誰,應該不是 httpd_sys_rw_content_t ...

      刪除
  5. 請問套件庫
    sudo vi /etc/yum.repos.d/nginx.repo
    進去更新之後
    [nginx]
    name=nginx repo
    baseurl=http://nginx.org/packages/centos/7/$basearch/
    gpgcheck=0
    enabled=1

    要如何儲存跳回root的畫面?

    回覆刪除
  6. 你好,在預設站台根目錄下建立的php檔案會變成一般檔案下載
    GOOGLE很久找不到解決方法,請問有哪個檔案要修改嗎?

    回覆刪除
    回覆
    1. 檢查一下 nginx 站台設定檔裡面,PHP 的段落有沒有問題? 有沒有實際符合系統的組態?

      刪除
  7. 請教,如果一個不懂程式只懂硬體的工程師,想在lemp開發php還是C++需要具備什麼工具?

    回覆刪除
    回覆
    1. 寫程式最重要的工具就是一台合適的電腦,還有一顆認真研究的心,沒了....
      剩下的就是去拜 Google 大神、去書店進貢香油錢,跟去教室跟老師求教了。

      刪除
  8. 想請教你圖片中使用的SSH程式是哪一個或著這不是SSH程式 ?

    回覆刪除
    回覆
    1. 我用的是 macOS 上面的 SSH Client: iTerm2 ...
      https://www.iterm2.com/

      刪除
  9. HI 我想情問一下 在你這篇的基礎上 如何安裝 Zabbix?
    我參考好多文章 都安裝失敗

    回覆刪除
    回覆
    1. Sorry,我沒有裝過 Zabbix,所以無法給你建議 ......

      刪除
  10. chcon: failed to create security context: : Invalid argument

    回覆刪除