由于项目的需要,我将学习如何在一台空的Ubuntu机器上,配置Node.js + MongoDB的生产环境,这里是整个的搭建配置流程,使用了DigitalOcean作为VPS,搭建了一个远程的环境,用来部署Node.js App。
搭建并配置VPS
在我们开始一切之前,我们首先需要一个可以访问的服务器。有许多的VPS可以供我们选择,例如AWS,阿里云,DigitalOcean等等,所以不必拘泥于DigitalOcean。不过,为了方便起见,建议根据教程一起,使用DigitalOcean来搭建服务器,因为它真的挺不错的。
如果你还没有DigitalOcean的账户,那么你可以点击下面这个链接,可以免费获得10美元,足够让你用两个月,还挺不错的吧。
在DigitalOcean上创建一个新的Droplet
在创建好账户,并登陆之后,你可以看到如下的界面,点击”Create Droplet”的按钮。
选择Ubuntu 16.04.3 x64 -> 选择最便宜的每月5美元的型号 -> 选择服务器的所在区域(我选了新加坡,因为感觉离得比较近吧) -> 添加SSH Key
这里,我是用的是Mac OS,所以可以打开terminal,输入如下命令查看是否已经存在SSH key:
当返回的列表中,有存在名为 id_rsa.pub 的文件时,说明系统中已经生成了SSH key,只需要复制就可以了,复制的命令为:
点击”New SSH Key”的按钮,将SSH Key粘贴进去,随便起一个名字,比如Louis’s MBP,然后保存。
在下面,为你的Droplet起一个名字,最后点击”Create”按钮创建它。
创建成功后,页面会跳转到Droplet列表页面,在新的Droplet上会显示它的IP地址,点击复制它。
打开terminal,输入如下命令,来连接到你的Droplet上:
对服务器进行基础的安全设置
当我们登录到服务器之后,我们需要对服务器做一些基础的配置,来确保它的安全性。
首先,我们要创建一个拥有 sudo 权限的新用户,在terminal中输入如下命令:
这个命令会要求我们输入密码,以及一些相关信息,直接回车就可以了。
创建完成后,我们可以使用 id 命令来查看user:
为了在服务器上运行某些命令,比如说restart services等,我们需要将我们的用户添加到 sudo 用户组里,输入如下命令:
执行完成后,再使用 id 命令查看一下louis的状态:
可以看出,我们的louis用户已经被添加到 sudo 用户组里了。
下面,我们要将我们的SSH key添加给我们的新用户,这样就可以使我们的新用户在登录的时候不需要输入密码了,因为我们打算禁止用户使用密码登录这个服务器来提高它的安全性,所以这一步很重要:
这里,在另一个terminal中,输入之前的 pbcopy 命令,来复制ssh key,点击paste之后,输入 ctrl+x,然后退出。要确认是否成功粘贴的话,可以使用如下命令检测:
在这之后,修改这个文件的权限并推出:
接下来,我们需要阻止使用密码的登录行为,因为每个服务器都有一个root用户,而且这是一个常见的攻击目标,它又有着非常强大的权限,所以最好是将它限制起来,确保没有人可以使用它:
现在,我们需要更新SSH的配置文件,来阻止密码登录,同时阻止使用root用户进行登录,输入如下命令来修改配置文件:
这个文件中,需要修改两个地方:
- PermitRootLogin Yes 改为 no
- PasswordAuthentication Yes 改为 no
TIPS: 可以使用 ctrl+w 来搜索内容进行修改
修改完成后,按下 ctrl+x 以及 y 推出编辑并保存。输入如下命令,重启ssh服务:
这时,新建一个terminal窗口,尝试使用root登录的话,应该会失败。显示Permission denied (publickey)。
接着,我们需要配置一个简单的防火墙,我们将只允许HTTP, HTTPS以及SSH。这将会减少很大一部分的安全隐患,当然这也只是简单的配置,这里不对安全做过多的深入了。
在启动完成后,可以使用如下命令查看防火墙的状态:
运行Node.js App
到目前为止,我们的服务器已经配置完成了,所以开始准备运行我们的App吧!
安装Git
在Droplet中,其实已经预装了Git,可以使用如下命令查看是否安装:
如果没有安装的话,安装起来也很方便:
安装MongoDB
安装MongoDB的步骤可以参照官方文档:https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/
首先,需要导入public key:
然后,选择对应的Ubuntu版本,来创建一个list file (Ubuntu 16.04):
更新apt-get:
安装最新稳定版本的MongoDB:
启动MongoDB:
要在本机上使用Robomongo连接到远程主机,由于我们关闭了密码验证,所以需要手动将远程主机的27017端口forward到我们的机器上,具体设置如下:
在Robomongo的连接面板中,server为127.0.0.1,端口号为27018。这样就可以使用Robomongo访问远程主机上的MongoDB了,还是很实用的。
安装Node.js
跟git相比,安装node.js要比较麻烦一点,因为有许多不同版本的node.js,所以我们要选择我们需要的版本,让 apt-get 来进行正确的更新。执行以下的命令,来获取并执行NodeSource提供的setup script:
当上面的执行完成了,我们就可以使用 apt-get 来安装node.js了:
安装完成后,可以查看版本号来检测是否安装成功:
下面我们使用一个小App进行测试:
安装nodemon:
安装dependencies:
由于这个小程序是运行在3000端口上的,所以我们要将防火墙的3000端口打开,这样才可以访问(后面Nginx可以反向代理)
运行App:
打开浏览器,输入地址:http://128.199.175.122:3000/ 就可以访问Node.js程序了。
使用PM2来管理Node.js App
到目前为止,已经可以手动启动并运行Node.js程序了,但是万一我们的服务器重启了,我们就得再重新执行一遍上述的步骤,这很麻烦,所以我们将要使用一个叫做PM2的process manager来管理我们的Node.js Apps。
安装PM2
|
|
使用PM2启动App
|
|
启动应用后,会得到上面的返回结果,说明app已经成功运行了。
设置服务器重启后自动重启应用
|
|
当执行 pm2 startup systemd 后,系统会返回一串命令要求你执行,这时复制粘贴并执行就可以了。
使用Let’s Encrypt获取免费的SSL Certificate
SSL一直以来因为昂贵和复杂成为其普及的障碍,但是现在,有些非常热心的人创造出了Let’s Encrypt这个好东西,使它变得便宜又简单了。所以我们现在要用它来提高我们域名的安全性。
安装Let’s Encrypt
首先,我们要安装一个Let’s Encrypt的依赖文件,叫做bc:
完成后,我们使用git,将文件复制进/opt/letsencrypt文件夹
将域名指向服务器
由于在生成SSL证书之前,我们需要先将域名指向我们的服务器。
所以这里,我们需要获取一个域名, 这里我使用了腾讯云的域名,目前还在实名认证审核中…😢
域名审核通过,我们继续,在TencentCloud的控制台将域名指向了我们的主机IP地址后,测试也通过了。
返回的地址正确!说明绑定已经成功了,这个域名已经可以成功访问了!
生成SSL证书
|
|
在输入上述命令之后,会要求你输入一个email地址,用于接收一些安全通知。然后会要求你输入你的域名,这里我们需要输入两个域名(louisnow.cn,www.louisnow.cn),使用逗号或者空格隔开就可以了。
为SSL证书设置自动续订
处于安全性考虑,Let’s Encrypt会在每90天后超期失效(一般付费的SSL证书都是一年时间),所以我们就需要为这个证书设置自动续订。
Let’s Encrypt也提供了续订的命令:
但是,如果每过90天,我们就登录服务器检查一遍是否过期,那么将会很蛋疼,所以这里我们需要一个工具为我们来完成自动续订的事情,它叫做 cron 。你可以在terminal中输入以下命令来编辑cron的任务:
这里会询问使用哪一种编辑器,由于nano还是比较简单的,所以我们继续使用nano。在文件的最底部输入如下命令:
将域名指向App
在上面的操作中,我们为了方便将3000端口开放出来方便访问调试,其实这种做法是不太安全的,所以我们现在要关闭3000端口,并使用nginx反向代理来完成对于App的访问。参考: UFW防火墙简单设置
这样,3000端口就关闭了,我们再尝试从外部访问3000端口应该是失败的。
安装Nginx
现在来安装Nginx,这里还是很方便的,使用apt-get就可以了:
接下来,我们要确保所有的流量都是在SSL上传输的,我们要将所有非SSL的流量重定向到SSL版本上,如果某人访问了http://www.louisnow.cn那么他会被自动重定向到https://www.louisnow.cn上,所以我们需要修改Nginx的配置文件:
使用 ctrl+k 删除文件中的所有内容,然后将下面的内容copy进去就可以了:
下面还有一步,只需要一行代码,就可以让我们的App更加安全,就是建立一个Diffie-Hellman-Group,虽然我也不是很清楚这里的原理,总之还是加上吧…:
然后,我们需要给SSL创建一个配置文件:
将下面的内容copy到打开的文件中并保存退出:
继续配置Nginx文件:
将下面的内容copy到之前的内容后面:
要注意将域名相关的地方进行替换,并且由于我们的App是运行在3000端口上的,所以在proxy_pass后面填上http://localhost:3000/
在启动服务器之前,我们需要先测试一下,看看有没有出问题:
这里我就出问题了,由于将配置文件中的域名写成 www.louisnow.cn 导致了错误,这里应该将 www 去掉就可以了,再次测试,通过!
最后,运行nginx即可:
访问www.louisnow.cn,当时发现页面不对啊,这里可能因为服务器还没刷新,所以我们回到terminal,重新启动一下nginx:
然后再回到浏览器,按住 shift+command+R 就可以了!
注册界面