[Third party service Note] - Vue + Node.js + Nginx + MySQL5.7, 第一次使用 VPS(Linode, DigitalOcean) 就可能會碰到的問題之如何簡單上手

Introduction & 前言

Linode

先說這篇文章僅用於筆記,如果您剛好、恰巧有專案是 前端 VUE 後端 NODE 想佈上虛擬主機上,不管是給客戶看還是自己當作品用,都可以接著往下看,亦或許您會在文章中圖找到一樣的問題,還有我怎麼蹶誒的。

這邊也不會去探討哪台虛擬主機比較好,但我會跟你說說為什麼我從 DigitalOcean 跳到 Linode 使用。


當程式完成後的下一步

滿滿程式碼

相信不管你學什麼前端,什麼後端,寫完程式碼後,下一步就是想要想辦法把作品呈現出來,雖然我們平常可以使用 GitHub+Heroku 其實就可以簡單呈現一個小作品,但缺點是 Heroku 太久沒動靜,需要一點時間喚醒,加上免費專案只能有五個。

基於上面的問題加上筆者最近剛好在幫家人做 Side Project 預約系統,目前已經到了完成一個小階段,需要呈現給家人看,最後決定使用虛擬主機來放置我的專案。

考量到以後可能還會有其他 Side Project 所以就挑選了便宜的主機來用。

然後就開始採坑之旅了。


主機筆者怎麼挑

因為本篇文章不是深入討論主機問題,所以筆者第一次挑選主機就是從 便宜、便宜、很便宜 這三個條件下去選擇,同事立馬推薦我 DigitalOcean一個月最低五美金的方案筆者覺得還行,沒有多想就開下去了。

因為後端使用 Node.js 加上開發是用 MacOS,所以筆者挑 CentOS 7.6(不挑8是因為同事認為 7 比較穩定,加上工作環境也都是用 7 碰到問題容易解決),而剛開始建立完機器虛擬主機會給你一個 IP Addresses,正常來說會是 IPv4

想知道 IPv4IPv6 有什麼不同可以點我 查看 認識IPv4與IPv6的差異

順帶一提,通常在建立過程中,會讓你選擇之後登入主機需要使用密碼或是 SSH,筆者建議兩個都填比較安全;簡單講解一下前者就字面上的意思,使用密碼登入,而 SSH 則是會有一組 id_rsaid_rsa.pub,這兩組 Key 可以用來識別你的身份,進而達到免密碼登入。

想知道 SSH 怎麼建立嗎?點我 查看 [教學] 產生SSH Key並且透過KEY進行免密碼登入


事前準備

上面筆者偷懶認為大概大家會看到文章 87% 已經知道怎麼做了,這邊在簡單提一下該準備什麼東西。

  • 一組網域(推薦 GoDaddy 註冊)

  • 一顆炙熱的寫 Code 心

為什麼要準備網域呢,待會這邊會用一張圖解釋一下,總之您可以先挑一個順眼的名稱註冊網域。


安裝環境

筆者再度簡單列出這次需要安裝的環境。

注意!因為每個人需要的不一樣,該裝的東西可能也會有些許差異,請自行斟酌。

請先進入到您自己得主機,通常會在終端機上輸入:

1
2
3
4
5
// 使用密碼登入
$ ssh root@xxx.xxx.xx.xx

// 使用 ssh 登入
$ ssh -i ~/.ssh/id_rsa root@xxx.xxx.xx.xx

xxx.xxx.xx.xx 為您的主機 IPv4 位置,而使用 ssh 需要您自己指定到您的 ssh 檔案位置。

設定時區

登入成功後,第一個需要做的不是安裝,是檢查自己的時區,因為錯誤的時區可能照成您的排程錯誤資料庫資料時間錯誤…等等。

1
$ date

這時候如果出現時間錯誤,可以改為自己得時區:

1
2
// 設定為亞洲台北
$ sudo timedatectl set-timezone Asia/Taipei

如何查看時區可以輸入:

1
$ timedatectl list-timezones

設定結束後記得再次輸入 date 查看時間對不對。

安裝 EPEL

有許多套件只有 EPEL 中才有,所以這邊我們需要先安裝:

1
$ sudo yum install epel-release

更新套件

安裝結束後我們需要更新一下我們所有的套件:

1
$ sudo yum upgrade

安裝 Nginx

這邊要講解為什麼要安裝 Nginx,但不會深入討論,有興趣可以參考 淺談Nginx之反向代理 中介紹反向代理,亦或是 深度詳解Nginx正向代理與反向代理?

DNS

先看看上方這張圖,通常我們會在網路輸入一串網址,比如 fonts.google.comtranslate.google.com,通常我們一個網域可能會有好幾個需要呈現的不同專案,就可以使用 主網域子網域 來實現,很清楚我們可以看到 google 就是主網域,fontstranslate 就是子網域。

但你會想,一台主機一個 IPv4 會對應到一個子網域,那我是不是一個專案只能放一台機器呢?

其實我們靠 Nginx 就可以達到,輸入一串網址,網址子網域都對到同一個 IPv4,然後再依靠 Nginx 去找尋對應網域名稱的專案。

DNS

找到對應專案的設定欓,會把設定檔裡面的 root 路徑的檔案顯示出來,這樣就能達成輸入什麼網址會顯示什麼內容出來了。

知道後廢話不多說我們開始安裝,使用 yum 裝 Nginx:

1
$ sudo yum install nginx

啟動 Nginx 服務:

1
$ sudo systemctl start nginx

接著檢查 nginx 是否正常:

1
$ sudo systemctl status nginx

然後很重要記得,永久啟用 Nginx 服務,重新開機後可自動啟動:

1
$ sudo systemctl enable nginx

這時候進入網頁輸入 IPv4 或是已經掛載上 Godady 的網域,應該就可以看到。

Nginx 預設頁面

PS: 如果進入網頁看到類似下面的網頁 無法連上這個網站 的話,有三種情況,第一個是有可能是你的防火牆沒打開,請記得打開防火牆,第二個是需要修改 /etc/firewalld/firewalld.conf 文件,最後則是需要輸入 sudo firewall-cmd --permanent --add-service=https 可能你沒開啟 https 服務

無法連上這個網站

第一種情況解決方式,輸入:

1
2
3
$ sudo firewall-cmd --add-service=dns --permanent

$ sudo firewall-cmd --reload

之後就能成功了!

打開防火牆

第二種情況解決放是,輸入 systemctl status firewalld 查看有無報錯,如果有問題會出現下圖情況:

防火牆出錯

這種情形請輸入:

1
2
3
4
$ vi /etc/firewalld/firewalld.conf

// 在命令模式(不是輸入的時候,點擊ESC退出輸入模式)輸入 /AllowZoneDrifting 搜索
// 接著將 AllowZoneDrifting=yes 改為 AllowZoneDrifting=no

然後輸入 systemctl restart firewalld 重啟防火牆,接著在輸入 systemctl status firewalld 查看還有無錯誤訊息,沒有就是排解了!

第三種也是最後一種情況可能是你的 https 沒有開啟,先輸入 sudo firewall-cmd --list-service 檢查你開了哪些服務,如果只出現 dhcpv6-client http ssh,那就是你的 https 沒有開,裡面缺什麼就是什麼沒開,解決方式就是輸入 sudo firewall-cmd --zone=public --permanent --add-service=https 如果 http 沒有就是修改最後的 service,例如 sudo firewall-cmd --zone=public --permanent --add-service=http 這樣,輸入完記得重啟 sudo firewall-cmd --reload 緊接著再輸入一次 sudo firewall-cmd --list-service 查看是否有加入這項服務了!

安裝 Git

1
$ yum install git

先查看版本號,確認是否安裝成功:

1
$ git --version

接著安裝結束後記得設定你的 git config

1
2
$ git config --global user.name 你的名字
$ git config --global user.email 你的信箱

接著輸入 git config --list 查看是否設定成功,之後就成功安裝了。

安裝 Node

因為我們必須使用到 Node.js 以及 NpmYarn 功能,所以必須先安裝 Node,但由於筆者喜歡將機器上的版本改為跟本地一樣,所以我們這邊需要先安裝 nvm,可以當他是 Node 的版本管理器。

由於這邊我們會使用到 wget 區抓取套件,所以我們先安裝:

1
yum install wget

接著輸入以下指令安裝:

1
$ wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.1/install.sh | bash

然後記得登出在登入!接著輸入 nvm --version 就會拿到目前得版號。

緊接著安裝 Node,可以使用 nvm ls-remote 可以查看所有可以提供安裝的版本,挑選你喜歡或熟悉的版本:

1
$ nvm install v12.16.1

安裝完成後輸入 node -v 查看是否安裝完成。

Yarn

因為有些人比較習慣使用 Yarn,這邊簡單說說怎麼安裝,有些教學會請您輸入 sudo yum install yarn 但會顯示沒有這個 package,所以這邊我們使用:

1
2
// 請注意一定要 -g
$ npm install yarn -g

設定 Nginx

這邊略過 clone 專案下來的過程,但還是筆記一下通常筆者會把專案放置在 /var/www/ 下面。

如果你是自己安裝 Nginx,會發現沒有 default.config 這個檔案,因為我們接下來的每一個專案都會有一個 ***.conf** 去引導使用者在瀏覽網頁時,主機會去拿哪一個專案丟給使用者看,如我沒有的話,也沒關係,使用下面我的範例建立一個,在自己去更改專案路徑即可。

在創建之前,你可以先使用 vi /etc/nginx/nginx.conf 去查看立面是否有顯示 include /etc/nginx/conf.d/*.conf 沒有可以自己加上去,基本上之後設定檔不是放在這個地方,就是放在 /etc/nginx/sites-available/ 或是 /etc/nginx/sites-enabled/ 都可以。

加上 vi /etc/nginx/nginx.conf 是為了能讓你專案的設定欓被吃到,不然還是會找不到你專案的位子。

include

檢查完確定 nginx 的設定欓就可以開始動手建立自己專案的設定欓了(記得通常是一個專案一個設定欓)。

範例程式碼可以複製這邊,或是上 Digitalocean NGINXConfig 試著配置出一份,通常都大同小異,只是內部有一些細微更改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
server {
listen 443 http2 ssl; ## listen for ipv4; this line is default and implied
#listen [::]:80 default ipv6only=on; ## listen for ipv6
# Make site accessible from http://localhost/
server_name frontend.abc.com; # 前面說的對應的網域就是設定在這

root /var/www/frontend/dist; # 你要渲染出來檔案的位子,這邊是 Vue 所以吃 dist
index index.php index.html index.htm; # 這邊會去抓結尾符合的檔案

# ssl_certificate #等等補上;
# ssl_certificate_key #等等補上;

# Disable sendfile as per https://docs.vagrantup.com/v2/synced-folders/virtualbox.html
sendfile on;
client_max_body_size 10M;

error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;

location / {
# proxy_pass http://127.0.0.1:1337; # 後端專案才需要使用,改為自己對應的 Port
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 後端專案才需要使用
try_files $uri $uri/ /index.html; # Vue 如果使用 History 模式請一定要加這行
}

error_page 404 /404.html;
location = /404.html {
root /var/www/errors;
internal;
}

# pass the PHP scripts to FastCGI server listening on socket
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
# fastcgi_pass unix:/var/run/php-fpm.sock;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_index index.php;
include fastcgi_params;
}

location ~* \.(jpg|jpeg|gif|png|css|js|ico|webp|tiff|ttf|svg)$ {
expires 5d;
}

# deny access to . files, for security
#
location ~ /\. {
log_not_found off;
deny all;
}

location ^~ /.well-known {
allow all;
auth_basic off;
}
}

這邊很重要!如果你是使用 Vue History 模式,請一定要在 location / { 那邊裡面加上 try_files $uri $uri/ /index.html; 不然你會發現怎麼切換路由就會出錯了。

接著很重要,檢查 Nginx 是否正常:

1
$ sudo systemctl status nginx

如果一切正常請重啟 Nginx

1
$ sudo systemctl restart nginx

設定 SSL

到這邊大致完成了,揭著我們必須讓我們的網址可以吃 443,也就是 https,有興趣可以參考 一文搞懂 HTTP 和 HTTPS 是什麼?兩者有什麼差別,簡單說最明顯的就是如果網站不是 443(https) 頁面左上角就會出現不安全。

而通常 SSL 是需要用買的,但這邊我們要當個免費仔(放心不是破解),而免費缺點是三個月需要更新一次,但別擔心各路大神都幫我們想好了怎麼自動更新憑證。

由於我們是 CentOS 7 所以輸入下列程式碼安裝:

1
$ yum install certbot

然後我們需要產生 SSL 憑證:

1
2
$ yum install python-certbot-nginx
$ certbot --nginx

通常如果您已經有設定 NginxConfig,他會自動問您是否要選擇那一個網域,選擇後會幫您建立一個 SSL 憑證,而且 config 裡面也會自動幫您更新。

成功產生出來會出現以下的文字提示:

1
Congratulations! You have successfully enabled "憑證網址"

為了不讓明證過期,我們可以輸入 vi /etc/crontab 去修改這隻檔案,然後在裡面空白處輸入:

1
2
# let's encrypt
0 */8 * * * root python -c 'import random; import time; time.sleep(random.random() * 3600)' && certbot renew > /tmp/cert-bot_renew.log

然後輸入 service crond restart,這樣就會 **每天檢查三次(00:00 08:00 16:00)**。

建立 SSL 之前必需要做的事情

因為我們輸入下列其中一個指令時,網址會檢查是否有對應到,所以必須先去 Godaddy 或是您買網域的地方,去把 DNS 設定好,這樣才能檢查通過,不然可是會失敗。

  1. certbot -> 產生憑證(需要輸入資訊)

  2. certbot –nginx (如果有 config 可以快速建立並且更新)


安裝資料庫

如果你已經有在其他服務申請資料庫,這個步驟可以跳過,但如果你跟筆者一樣安裝在虛擬主機上,就可以照著以下步驟走。

首先確定你要安裝 MySQL 5.7 還是 MySQL 8.0 兩者差別可以參考 **MySQL 8.0正式版來了! 高負載讀寫效能是5.7版的2倍**,這邊不過多討論。

  • 首先我們需要用到 yum-utils 套件,下面會用到 yum-config-manager 指令:
1
$ sudo yum install yum-utils -y
  • 下載安裝相關套件:

接著安裝套件,通常看到的教學文章會安裝指定版本號套件,下面這個會將幾個版本的套件包含進去

1
$ sudo yum localinstall https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm -y
  • 啟用要安裝的 MySQL 5.7 源:

因為接下來我們需要安裝 5.7 版本,先將剛剛包含幾個本版進去的套件 MySQL 8.0 關閉,並啟用 5.7

1
2
$ sudo yum-config-manager --disable mysql80-community
$ sudo yum-config-manager --enable mysql57-community
  • 檢查 MySQL Yum 源是否為 5.7 版本:
1
2
3
4
$ sudo yum repolist enabled | grep "mysql.*-community.*"
// mysql-connectors-community/x86_64 MySQL Connectors Community 118
// mysql-tools-community/x86_64 MySQL Tools Community 95
// mysql57-community/x86_64 MySQL 5.7 Community Server 364

如果是需要安裝 8.0 最後一個會看到 MySQL 8.0 Community Server

  • 安裝 MySQL,並啟用 MySQL 服務,然後加上每次重開機會啟動的設定,在檢查啟動狀態:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 安裝
$ sudo yum install mysql-community-server -y
// 啟用
$ sudo systemctl start mysqld
// 讓每次開機 MySQL 服務會自動被啟動
$ sudo systemctl enable mysqld
// 檢查啟動狀態
$ sudo systemctl status mysqld
// mysqld.service - MySQL Server
// Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled)
// Active: active (running) since Tue 2019-09-10 20:37:18 CST; 48s ago
// Docs: man:mysqld(8)
// http://...略//
// Main PID: 1825 (mysqld)
// CGroup: /system.slice/mysqld.service
// 1825 /usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysql...
//
// Jan 04 22:30:33 centos7-cli.lab.example.com systemd[1]: Starting MySQL Server...
// Jan 04 22:30:36 centos7-cli.lab.example.com systemd[1]: Started MySQL Server.
  • 安裝完成後,現在的密碼會是一組暫時密碼,所以我們必須要更改成自己會記得的密碼,先輸入下列程式碼拿取暫時密碼,請記得要截圖留存下來,或是把最後那串密碼複製存下來,等等馬上會用到
1
2
$ sudo grep 'temporary password' /var/log/mysqld.log
2021-01-04T14:08:05.129641Z 1 [Note] A temporary password is generated for root@localhost: +ew=SLsfd1#H
  • 更改密碼並且填寫相關設定:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ sudo mysql_secure_installation

// Securing the MySQL server deployment.

// Enter password for user root: 這邊請輸入剛剛拿到的臨時密碼

// The existing password for the user account root has expired. Please set a new password.

// New password: 請輸入新密碼

// Re-enter new password: 請再次輸入新密碼
// The 'validate_password' plugin is installed on the server.
// The subsequent steps will run with the existing configuration
// of the plugin.
// Using existing password for root.

//...下略

請注意: 密碼必須包含一個大寫字母、一個小寫字母、一個數字和一個特殊符號,長度至少為 8 個字元

基本上後面開始都是一些問題,像是 是否移除 anonymous 匿名者帳號、禁止 root 從非本機登入、移除測試資料庫…等等,基本上全都填寫 **Y(同意/確定)**。

  • 查看版本:

這時候輸入指令查看是否安裝完成:

1
2
$ sudo mysqld -V
mysqld Ver 5.7.32 for Linux on x86_64 (MySQL Community Server (GPL))
  • 開啟 3306 防火牆

資料庫預設都是吃 3306port 的,如果不打開會出現 Connection Refused,然後我們要設定一組可以遠端從其他地方登入的帳號,我們總不能每次都連上主機再去連進資料庫吧。

先查看防火牆是否開啟:

1
2
$ firewall-cmd --query-port=3306/tcp
// No 代表沒開啟

開啟防火牆:

1
$ firewall-cmd --zone=public --add-port=3306/tcp --permanent

如果要關閉可以輸入:

1
$ firewall-cmd --zone=public --remove-port=3306/tcp --permanent

重新啟動防火牆:

1
$ firewall-cmd --reload
  • 登入資料庫:

接著我們要去新增可以任意登入的用戶,我們先登入:

1
2
$ mysql -u root -h localhost -p
// Enter password: 接著輸入密碼

然後新增可以遠端登入的帳號:

1
mysql> grant all privileges on *.* to '使用者名稱'@'IP位置' identified by'要登入的密碼';

// 如果想要任何地方都可以連線請在IP位置輸入 % 範例如下:
mysql> grant all privileges on *.* to 'root'@'%' identified by'abc';

上面 . 為權限,這個意思是可以訪問所有的資料庫及資料表。

這樣就新增成功了,之後在任何地方都可以使用 root 登入。

使修改重新生效:

1
mysql> flush privileges;
  • 試看看遠端連線吧!

額外小坑

出現 “permissions are too open” 的錯誤

這是您的 SSH 的權限問題,只需要輸入 chmod 400 ~/.ssh/id_rsachmod 600 ~/.ssh/id_rsa 即可解決

VUE 的 Router 導致頁面出現 404

由於我們在 Nginx 已經設定好路由就是吃到 /var/www/frontend/distindex,如果被路由轉導後,可能會變成 https://xxx.xxx/index/dashboard/edit/1 之類的網址,這時候就會找不到對應該渲染的畫面。

解決方式其實很簡單,只需要在 Nginx 的設定欓修改一下:

1
2
3
4
// 找到 location 並在裡面加上 try_files 這行即可
location / {
try_files $uri $uri/ /index.html;
}

頁面出現 502 Bad Gateway

查看 NginxError config

1
2
3
4
5
// 詳細位置可先查看
$ vi /etc/nginx/nginx.conf

// 接著找到 err 的位子
$ vi /var/log/nginx/error.log

裡面如果出現了 (13: Permission denied) 的關鍵字,代表你的那個專案的 Nginx 設定檔指定的 Port 是權限不足的。

這時候輸入 semanage port --list 找尋 http_port_t 可以看到後面有一串 port 號,如果沒有你的就代表需要自己新增上去。

1
$ semanage port --add --type http_port_t --proto tcp "你要新增的 Port 號"

然後再次輸入剛剛的 semanage port --list 就會看見了!

Vue Build 出現錯誤

如果在使用 npm buildyarn build 的時候出現類似下圖錯誤:

Node 錯誤

代表你的 Node 版本有問題,筆者發生這問題是因為自己的 Node 版本太新了,舊的某些套件不支援,所以必須要改變版本或是更新套件,筆者安裝和自己本地一樣的舊版本就解決了。

如果使用 nvm 的話,可以先使用 Node -v 查看自己本地的版本,然後再使用 nvm ls-remote 查看可安裝版本,接著使用 nvm install 版本號 安裝指定版本,最後可以使用 nvm ls 查看目前可使用的版本!

使用 nvm 安裝得好處就不多說了,主要可以想成就是拿來管理 Node 版本的管理工具,推薦安裝一下。


Conclusion & 結論

沒想到 2021 第一篇文章竟然是先記錄環境設定的筆記,其實原本打算先寫一篇完成全端後的心得文,也算是完成自己寫程式兩年的期許,完成電商的小里程碑。

雖然嘴裡常常在寫不出程式碼時不時的咒罵,但其實親身體會一次才是最好的學習,並且會有滿滿德成就感。

最後要說說,上面有提到為什麼後來改用 Linode 了,因為筆者在 DigitalOcean 第一次更改環境時,最後輸入了 Reboot 想重啟機器,但關掉之後就再也連不進去,連 Console 也不行,最後整個砍掉重新在建立一次。

就在今天弄了一天之後筆者在安裝 Mysql 的過程卡住了,索性關閉機器,再度重啟時,又出現了下面這張圖,網站的 Console 也不能開啟,一氣之下就改用其他家主機了。

怎麼也連不上了

這邊真的要再度感謝幫助我的各路大神,沒有你們我沒辦法走這麼遠,謝謝你們!


參考網站