wufan0 2019-06-26
作为一个前端开发工程师,每天和浏览器、业务代码打交道,对于“前端”的概念算是比较熟悉了,主流的框架、工具等都能玩得转,但总觉得自己一直都被禁锢在小小的所谓“前端”的圈子中——因为除此之外的知识点还是比较薄弱的。
后来在公司里面获得了一个轮岗的机会,进入到了运维团队去学习,眼界也开阔了很多,对于自身水平的认识也更加深入,迫不及待想要提升自己“前端知识”以外的技能树。
由于运维团队经常会跟服务器打交道,那么我何不干脆就从服务器开始,好好折腾一遍呢?
曾经考虑过购买腾讯云或者阿里云等国内服务器,但是由于国内总所周知的原因,许多资源的下载要么特别慢,要么干脆直接跪了,动不动就要切换源。同时如果域名绑定了国内的服务器,都需要进行备案,实在是无比麻烦。毫无疑问,我最终选择了国外的服务器,世界瞬间就清净了……
关于国外的服务器选购,是见仁见智的事情,我选购的是一台搬瓦工20G KVM服务器,5美元/月,买了不吃亏买了不上当,然后安装了Centos 7 x86_64 bbr系统,接下来就可以愉快地玩耍了。
搭个什么服务都好,总不能让别人背自己的ip,如果能够拥到一个拉风的域名还是很赞的。于是我就去万网,直接以自己的英文名字jrainlau
申请了一个jrainlau.com
域名,一年才55块RMB,真的超值哦~
很简单的下单、支付,然后我就拥有了自己的专属域名,接下来就是进行DNS解析了。
进入阿里云的控制台,找到云解析DNS
,点进去就能看到我们的域名解析信息了。添加两条类型为A
的记录,统统指向服务器的ip地址即可:
在域名解析生效前的10分钟里面,足够我们在服务器上配置好Nginx了。
首先ssh登录服务器:
ssh [email protected] -p yyyy
输入搬瓦工提供的登录密码之后,顺利登入。
但是如果每次登录服务器都要输入一遍那乱码般的密码,是很痛苦的一件事,所以果断使用ssh-key来实现免密登录。
第一步,生成秘钥(如果本机已存在可省略这一步)
ssh-keygen -t rsa
按照提示选择秘钥所存放的目录(~/.ssh/
),密码留空,最后可以在设定的目录里找到生成的秘钥:
第二步,上传秘钥到服务器
ssh-copy-id [email protected] -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的欢迎页啦~
看到左上角“不安全”三个字,心里是非常不爽的,于是马上进行下一步工作,上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
由于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
服务器已经准备了,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项目了。
刚才的操作仅仅是作为初次部署,如果以后代码有改动,还需要我们登录服务器,进入到对应的项目目录,手动执行git pull
,然后手动重启服务器(如果pm2启动了watch模式可以省略这一步),相当麻烦。能不能有一种办法,能够在我提交代码的时候就自动更新服务器的代码,并自动重启服务器呢?travis-ci
就是来实现这个目的的。
travis-ci支持公开项目和私有项目,是通过.org
和.com
后缀来区分的。以我的一个公开项目为例,首先进入https://travis-ci.org/ 官网,登录我的github账号,然后会看到如下页面:
找到需要集成travis-ci的项目,点击它前面的开关即可。
此时在travis-ci上的操作暂时告一段落,但是页面先别关掉,先放在一边。
接下来,我们回到本地开发机器,通过git clone
命令把这个项目克隆到本地,然后在项目根目录下添加一个.travis.yml
文件。这个文件是travis-ci持续集成的关键,它定义了你所有持续集成的操作。为了简单起见,我们仅仅使用它进行自动化部署:
language: node_js node_js: - 9.3.0 after_success: - ssh [email protected] -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的配置,其实我们已经具备了这一条件,之不过还需要多几步的操作。
在本地通过gem
安装travis
命令行工具(macOS默认支持ruby):
gem install travis
使用travis登录:
travis login
然后输入github的账号密码即可。
加密本地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的页面,进入项目,就能够看到持续集成的效果了:
这时候回到服务器,运行pm2 logs
,会看到服务已经被自动重启的日志记录,至此持续集成及部署功能完美成功!
这一番折腾下来,总算把服务器、建站、持续部署等知识囫囵摸了一遍,对这些技术栈也算有了一些粗浅的见解。接下来还有更多好玩的东西需要进行探索,毕竟这只是一个开始,大家一起共勉吧~