不僅僅是前端er——折騰伺服器武裝自己

Jrain發表於2019-01-31

寫於 2018.02.19

不僅僅是前端er——折騰伺服器武裝自己

前言

作為一個前端開發工程師,每天和瀏覽器、業務程式碼打交道,對於“前端”的概念算是比較熟悉了,主流的框架、工具等都能玩得轉,但總覺得自己一直都被禁錮在小小的所謂“前端”的圈子中——因為除此之外的知識點還是比較薄弱的。

後來在公司裡面獲得了一個輪崗的機會,進入到了運維團隊去學習,眼界也開闊了很多,對於自身水平的認識也更加深入,迫不及待想要提升自己“前端知識”以外的技能樹。

由於運維團隊經常會跟伺服器打交道,那麼我何不乾脆就從伺服器開始,好好折騰一遍呢?

一、購買伺服器

曾經考慮過購買騰訊雲或者阿里雲等國內伺服器,但是由於國內總所周知的原因,許多資源的下載要麼特別慢,要麼乾脆直接跪了,動不動就要切換源。同時如果域名繫結了國內的伺服器,都需要進行備案,實在是無比麻煩。毫無疑問,我最終選擇了國外的伺服器,世界瞬間就清淨了……

關於國外的伺服器選購,是見仁見智的事情,我選購的是一臺搬瓦工20G KVM伺服器,5美元/月,買了不吃虧買了不上當,然後安裝了Centos 7 x86_64 bbr系統,接下來就可以愉快地玩耍了。

不僅僅是前端er——折騰伺服器武裝自己

二、購買域名

搭個什麼服務都好,總不能讓別人背自己的ip,如果能夠擁到一個拉風的域名還是很讚的。於是我就去萬網,直接以自己的英文名字jrainlau申請了一個jrainlau.com域名,一年才55塊RMB,真的超值哦~

很簡單的下單、支付,然後我就擁有了自己的專屬域名,接下來就是進行DNS解析了。

進入阿里雲的控制檯,找到雲解析DNS,點進去就能看到我們的域名解析資訊了。新增兩條型別為A的記錄,統統指向伺服器的ip地址即可:

不僅僅是前端er——折騰伺服器武裝自己

三、安裝Nginx

在域名解析生效前的10分鐘裡面,足夠我們在伺服器上配置好Nginx了。

首先ssh登入伺服器:

ssh root@xxx.xxx.xxx.xxx -p yyyy
複製程式碼

輸入搬瓦工提供的登入密碼之後,順利登入。

但是如果每次登入伺服器都要輸入一遍那亂碼般的密碼,是很痛苦的一件事,所以果斷使用ssh-key來實現免密登入。

  • 第一步,生成祕鑰(如果本機已存在可省略這一步)
    ssh-keygen -t rsa
    複製程式碼
    按照提示選擇祕鑰所存放的目錄(~/.ssh/),密碼留空,最後可以在設定的目錄裡找到生成的祕鑰:

不僅僅是前端er——折騰伺服器武裝自己

  • 第二步,上傳祕鑰到伺服器
    ssh-copy-id root@xxx.xxx.xxx -p yyyy
    複製程式碼
    然後按照提示輸入一遍密碼就可以了。以後想要登入伺服器就可以直接免密登入啦!

做完剛才的“分支任務”,回到我們配置Nginx的主線。

按照Nginx官網的文件,在CentOS中安裝Nginx是非常簡單的:

yum install -y nginx
複製程式碼

但是在實際操作中,卻發現一直提示No package nginx available。搜了一圈,Stack Overflow裡面的回答都是因為可能沒有安裝epel,於是馬上嘗試之:

yum install -y epel-release
複製程式碼

奇怪的是,執行結果提示epel已經存在,為nothing to do。然後當我嘗試安裝nginx的時候,發現還是no package nginx available。嘗試列出yum所有的源,發現根本沒有epel源:

yum repolist

源標識                          源名稱                                                                      狀態
base/7/x86_64                   CentOS-7 - Base                                                             9,590+1
extras/7/x86_64                 CentOS-7 - Extras                                                               388
updates/7/x86_64                CentOS-7 - Updates                                                          1,922+7
複製程式碼

後來經過一番折騰,才找到解決辦法:

# 首先進入/yum.repos.d目錄
cd /etc/yum.repos.d

# 然後編輯epel.repo檔案
vi epel.repo

[epel]
name=Extra Packages for Enterprise Linux 7 - $basearch
#baseurl=http://download.fedoraproject.org/pub/epel/7/$basearch
mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-7&arch=$basearch
failovermethod=priority
enabled=0
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7

[epel-debuginfo]
name=Extra Packages for Enterprise Linux 7 - $basearch - Debug
#baseurl=http://download.fedoraproject.org/pub/epel/7/$basearch/debug
mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-debug-7&arch=$basearch
failovermethod=priority
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
gpgcheck=1

[epel-source]
name=Extra Packages for Enterprise Linux 7 - $basearch - Source
#baseurl=http://download.fedoraproject.org/pub/epel/7/SRPMS
mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-source-7&arch=$basearch
failovermethod=priority
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
gpgcheck=1
複製程式碼

可以看到,[epel][epel-source]裡面的enabled都是0,解決辦法就在這裡,只要把0改成1,儲存退出後即可。

現在我們重新執行yum repolist,會發現epel源已經被加上了:

源標識                          源名稱                                                                      狀態
base/7/x86_64                   CentOS-7 - Base                                                             9,590+1
elrepo-kernel                   ELRepo.org Community Enterprise Linux Kernel Repository - el7                    37
epel/x86_64                     Extra Packages for Enterprise Linux 7 - x86_64                               12,277
epel-source/x86_64              Extra Packages for Enterprise Linux 7 - x86_64 - Source                           0
extras/7/x86_64                 CentOS-7 - Extras                                                               388
nodesource/x86_64               Node.js Packages for Enterprise Linux 7 - x86_64                                 22
updates/7/x86_64                CentOS-7 - Updates                                                          1,922+7
repolist: 24,236
複製程式碼

再執行yum install -y nginx,發現終於能夠成功安裝了!

nginx version: nginx/1.12.2
複製程式碼

接下來只要用一條指令即可開啟nginx:

nginx
複製程式碼

經過上面的一番折騰,域名的DNS解析早已生效了,此時輸入域名並回車,就能看到nginx的歡迎頁啦~

不僅僅是前端er——折騰伺服器武裝自己

四、使用HTTPS

看到左上角“不安全”三個字,心裡是非常不爽的,於是馬上進行下一步工作,上HTTPS。

由於是個人伺服器,所以免費證書已經足夠了,另外為了方便起見,所以我使用了certbot這個工具來幫我把伺服器升級成HTTPS。

首先通過yum下載安裝certbot

yum install certbot
複製程式碼

由於certbot伺服器在驗證域名的時候,會通過HTTP的方式訪問一個由certbot生成的靜態檔案,所以我們首先要在nginx裡面進行配置:

進入/etc/nginx,然後編輯nginx.conf,在server裡面新增下列兩個location規則:

location ^~ /.well-known/acme-challenge/ {
   default_type "text/plain";
   root     /usr/share/nginx/html;
}

location = /.well-known/acme-challenge/ {
   return 404;
}
複製程式碼

可以看到,上面的root我是指向了/usr/share/nginx/htm,這個目錄是可以隨便指定的,我這麼寫完全是為了偷懶。

nginx配置好了以後,就可以使用certbot生成證書了:

# certbot certonly --webroot -w <root url> -d <hostname>

certbot certonly --webroot -w /usr/share/nginx/html/ -d xxxx.com
複製程式碼

如果看到下列的輸出,就證明證書已經生成成功了:

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/xxxx.com/fullchain.pem. Your cert
   will expire on 20XX-09-23. To obtain a new or tweaked version of
   this certificate in the future, simply run certbot again. To
   non-interactively renew *all* of your certificates, run "certbot
   renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le
複製程式碼

證書已經準備好了,我們還需要nginx的支援。重新開啟/etc/nginx/nginx.conf,然後把註釋掉的https server給註釋回來:

server {
    listen       443 ssl http2 default_server;
    listen       [::]:443 ssl http2 default_server;
    server_name  xxxx.com;
    root         /home/www;

    ssl_certificate "/etc/letsencrypt/live/xxxx.com/fullchain.pem";
    ssl_certificate_key "/etc/letsencrypt/live/xxxx.com/privkey.pem";
	ssl_trusted_certificate /etc/letsencrypt/live/xxxx.com/chain.pem;

    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;

    location / {
    }

    error_page 404 /404.html;
        location = /40x.html {
    }

    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
    }
}
複製程式碼

ps: 上面的root我給配置了/home/www目錄,意味著以後只要是放在該目錄下的靜態資原始檔夾,我都可以通過https://xxx.com/資料夾名直接進行訪問,更多關於nginx的配置請參考官方文件。

最後重啟一下nginx,就可以檢驗我們的頁面是否已經打上小綠標了:

nginx -s reload
複製程式碼

不僅僅是前端er——折騰伺服器武裝自己

由於certbot所使用的letsencrypt證書只有90天的有效期,所以我們需要對它定期自動更新。

首先模擬更新:

sudo certbot renew --dry-run

# 看到如下輸出證明模擬更新成功
-------------------------------------------------------------------------------
Processing /etc/letsencrypt/renewal/your.domain.com.conf
-------------------------------------------------------------------------------
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates below have not been saved.)

Congratulations, all renewals succeeded. The following certs have been renewed:
  /etc/letsencrypt/live/xxxx.com/fullchain.pem (success)
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates above have not been saved.)
複製程式碼

然後就可以使用crontab -e命令來實現自動化了:

sudo crontab -e

#新增配置,每週一半夜3點00分執行renew:

00 3 * * 1 /usr/bin/certbot renew  >> /var/log/le-renew.log
複製程式碼

五、部署靜態頁面與Node.js專案

伺服器已經準備了,HTTPS也弄好了,那麼接下來就可以部署我們的靜態頁面與nodejs專案了。

從前面的nginx配置可以知道,nginx對於域名為xxxx.com的請求,都會請求到/home/www目錄下,所以我們通過git或者scp等方式把靜態資源目放置在/home/www目錄下即可。比方說我的markcook專案:

cd /home/www

git clone https://github.com/jrainlau/markcook -b gh-pages
複製程式碼

此時訪問 jrainlau.com/markcook 即可訪問到專案的頁面。

對於nodejs專案,我們使用pm2來守護程式,讓專案在後臺執行。首先需要安裝nodejs,然後再安裝pm2:

curl -sL https://rpm.nodesource.com/setup_9.x | bash -
yum install nodejs

npm i pm2 -g
複製程式碼

接下來依然把nodejs專案通過git放置在/home/www目錄下,進入目錄,執行下列命令:

npm i

pm2 start index.js --name my-server

┌─────────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────┬───────────┬──────┬──────────┐
│ App name    │ id │ mode │ pid  │ status │ restart │ uptime │ cpu │ mem       │ user │ watching │
├─────────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────┼───────────┼──────┼──────────┤
│  my-server  │ 0  │ fork │ 2306 │ online │ 22      │ 7h     │ 0%  │ 46.2 MB   │ root │ disabled │
└─────────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────┴───────────┴──────┴──────────┘
 Use `pm2 show <id|name>` to get more details about an app
複製程式碼

最後在nginx.conf裡面新增一條代理規則(假設node服務埠為3000):

location /my-server/ {
  proxy_pass  http://localhost:3000
}
複製程式碼

這樣,就能夠通過https://xxxx.com/my-server/訪問到nodejs專案了。

六、使用travis-ci實現持續部署

剛才的操作僅僅是作為初次部署,如果以後程式碼有改動,還需要我們登入伺服器,進入到對應的專案目錄,手動執行git pull,然後手動重啟伺服器(如果pm2啟動了watch模式可以省略這一步),相當麻煩。能不能有一種辦法,能夠在我提交程式碼的時候就自動更新伺服器的程式碼,並自動重啟伺服器呢?travis-ci就是來實現這個目的的。

travis-ci支援公開專案私有專案,是通過.org.com字尾來區分的。以我的一個公開專案為例,首先進入https://travis-ci.org/ 官網,登入我的github賬號,然後會看到如下頁面:

不僅僅是前端er——折騰伺服器武裝自己

找到需要整合travis-ci的專案,點選它前面的開關即可。

不僅僅是前端er——折騰伺服器武裝自己

此時在travis-ci上的操作暫時告一段落,但是頁面先別關掉,先放在一邊。

接下來,我們回到本地開發機器,通過git clone命令把這個專案克隆到本地,然後在專案根目錄下新增一個.travis.yml檔案。這個檔案是travis-ci持續整合的關鍵,它定義了你所有持續整合的操作。為了簡單起見,我們僅僅使用它進行自動化部署

language: node_js
node_js:
- 9.3.0
after_success:
- ssh root@xxx.xxx.xxx.xxx -p yyy 'cd /home/www/taxi-server && git pull && pm2 restart taxi-server'

複製程式碼

可以看到,我給她定義了執行環境為node.js 9.3.0,在構建成功(其實啥也沒構建)之後,自動登入伺服器,拉取最新程式碼,重啟pm2。

大家都知道,登入伺服器是要輸入密碼的,即使是travis-ci幫我們自動化進行,這一步也免不了。但是由於輸入密碼的步驟是互動的,自動化處理不了,所以我們也要為travis-ci搞一套“免密登入”。經過上文ssh-key的配置,其實我們已經具備了這一條件,之不過還需要多幾步的操作。

  1. 本地通過gem安裝travis命令列工具(macOS預設支援ruby):

    gem install travis
    複製程式碼
  2. 使用travis登入:

    travis login
    複製程式碼

    然後輸入github的賬號密碼即可。

  3. 加密本地ssh-key並自動寫入.travis.yml

    # --add參數列示自動新增指令碼到.travis.yml檔案中
    travis encrypt-file ~/.ssh/id_rsa --add
    複製程式碼

這時會看到.travis.yml多了一段before_install的內容:

before_install:
- openssl aes-256-cbc -K $encrypted_e65149523857_key -iv $encrypted_e65149523857_iv
  -in id_rsa.enc -out ~\/.ssh/id_rsa -d
複製程式碼

然後把最後一行的“\”轉義符刪掉,並換行頂格新增如下兩條內容:

- chmod 600 ~/.ssh/id_rsa
- echo -e "Host xxx.xxx.xxx.xxx\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
複製程式碼

切記把xxx.xxx.xxx.xxx換成你伺服器的IP。

最後把新增.travis.yml的專案push到github即可。

重新回到travis-ci.org的頁面,進入專案,就能夠看到持續整合的效果了:

不僅僅是前端er——折騰伺服器武裝自己

不僅僅是前端er——折騰伺服器武裝自己

這時候回到伺服器,執行pm2 logs,會看到服務已經被自動重啟的日誌記錄,至此持續整合及部署功能完美成功!

尾聲

這一番折騰下來,總算把伺服器、建站、持續部署等知識囫圇摸了一遍,對這些技術棧也算有了一些粗淺的見解。接下來還有更多好玩的東西需要進行探索,畢竟這只是一個開始,大家一起共勉吧~

相關文章