不仅仅是前端er——折腾服务器武装自己

wufan0 2019-06-26

不仅仅是前端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

此时访问 https://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,会看到服务已经被自动重启的日志记录,至此持续集成及部署功能完美成功!

尾声

这一番折腾下来,总算把服务器、建站、持续部署等知识囫囵摸了一遍,对这些技术栈也算有了一些粗浅的见解。接下来还有更多好玩的东西需要进行探索,毕竟这只是一个开始,大家一起共勉吧~

相关推荐