本文于2019年1月19日有更新,添加了 systemd
守护进程的配置方法。
毕业论文写完了、答辩搞定了,回家呆一周之后就要去北京当烟酒僧了,在长春的同学该考研的考研、该忙毕业的忙毕业,大家都没时间搭理我,一个人在家好无聊……没错,我就是超级边缘人螺丝Ỏ̷͖͈̞̩͎̻̫̫̜͉̠̫͕̭̭̫̫̹̗̹͈̼̠̖͍͚̥͈̮̼͕̠̤̯̻̥̬̗̼̳̤̳̬̪̹͚̞̼̠͕̼̠̦͚̫͔̯̹͉͉̘͎͕̼̣̝͙̱̟̹̩̟̳̦̭͉̮̖̭̣̣̞̙̗̜̺̭̻̥͚͙̝̦̲̱͉͖͉̰̦͎̫̣̼͎͍̠̮͓̹̹͉̤̰̗̙͕͇͔̱͕̭͈̳̗̭͔̘̖̺̮̜̠͖̘͓̳͕̟̠̱̫̤͓͔̘̰̲͙͍͇̙͎̣̼̗̖͙̯͉̠̟͈͍͕̪͓̝̩̦̖̹̼̠̘̮͚̟͉̺̜͍͓̯̳̱̻͕̣̳͉̻̭̭̱͍̪̩̭̺͕̺̼̥̪͖̦̟͎̻̰_Ỏ̷͖͈̞̩͎̻̫̫̜͉̠̫͕̭̭̫̫̹̗̹͈̼̠̖͍͚̥͈̮̼͕̠̤̯̻̥̬̗̼̳̤̳̬̪̹͚̞̼̠͕̼̠̦͚̫͔̯̹͉͉̘͎͕̼̣̝͙̱̟̹̩̟̳̦̭͉̮̖̭̣̣̞̙̗̜̺̭̻̥͚͙̝̦̲̱͉͖͉̰̦͎̫̣̼͎͍̠̮͓̹̹͉̤̰̗̙͕͇͔̱͕̭͈̳̗̭͔̘̖̺̮̜̠͖̘͓̳͕̟̠̱̫̤͓͔̘̰̲͙͍͇̙͎̣̼̗̖͙̯͉̠̟͈͍͕̪͓̝̩̦̖̹̼̠̘̮͚̟͉̺̜͍͓̯̳̱̻͕̣̳͉̻̭̭̱͍̪̩̭̺͕̺̼̥̪͖̦̟͎̻̰。
本着打发时间的目的,给博客加了个留言板,部署程序的时候遇到了不少相当有意思的问题,所以写了这篇教程记录一下各种各样的踩坑历史d(`・∀・)b。
这篇文章将包含如下内容:使用 Nginx 作反向代理配置服务器时 Node 程序的坑点、如何为 Node 程序配置 Let’s Encrypt 的 SSL 证书、如果你打算使用 WebSocket 技术的话,需要处理的雷点。
Node.js 程序配置
获取客户端真实 IP
利用 Nginx 的反向代理功能连接外网与服务器上的 Node 程序会令其无法通过 req.connection.remoteAddress
获得客户端的真实 IP,这个时候需要修改获得 IP 的方法,使用 request.headers['X-Real-IP']
,Socket.io 则可以使用 socket.handshake.headers["x-real-ip"]
。
同时 Nginx 的 location
块内需要增加如下语句传递真实IP:
1 | proxy_set_header X-Real-IP $remote_addr; |
(事实上,X-Real-IP
和 X-Forwarded-For
存在区别,本文对此不做过多说明,只是简单的使用了 X-Real-IP
,有需要的读者可以自行搜索相关内容。)
程序持久化
利用Node写的程序有个特点,一旦出错服务端就会崩溃,我们肯定不能每次都手工重启它,因此需要一个持久化工具。持久化工具有很多,比如forever
或者pm2
,本例中介绍两种持久化工具, pm2 和 systemd,个人推荐后者。
使用 pm2 作为持久化工具
既然你用了 Node,服务器上自然是装了 npm ,我们使用 npm 安装 pm2。
1 | npm install -g pm2 |
安装完毕之后就可以利用 pm2 启动服务端程序了,假设入口文件是 index.js
,那么我们通过这个命令持久化该程序:
1 | pm2 start index.js |
我们还可以停止某一程序,或者从 pm2 的持久化列表将它删除:
1 | pm2 stop index.js |
如果你想要看某一程序的崩溃日志,可以使用如下命令:
1 | pm2 logs index.js |
使用 systemd 建立守护进程
在 /etc/systemd/system
建立一个以 .service
为扩展名的配置文件,比如:
1 | vim /etc/systemd/system/my-node-app.service |
插入以下内容:
1 | [Unit] |
刷新 systemd
守护进程列表:
1 | sudo systemctl daemon-reload |
启动你的服务:
1 | sudo service [YOUR SERVICE FILE NAME] start |
注意,替换方括号内的内容,不包含文件扩展名 .service
。
查看服务情况:
1 | service [YOUR SERVICE FILE NAME] status |
如果显示服务启动成功,则可以设置该服务开机自动启动:
1 | sudo systemctl enable [YOUR SERVICE FILE NAME] |
Nginx配置书写
注:如果你没做什么妖艳的配置的话,Nginx 的配置目录会被放在/etc/nginx/conf.d
里,在里面新建一个conf
文件作为单独的站点配置就可以了。
基础配置
如果你使用了自己的证书,那么可以这样设置你的 Nginx 配置文件(方括号内的内容需要手动设置):
1 | server { |
如果你打算使用 Let’s Encrypt,则不应使用本配置模板,具体参见下一小节。
如果你使用了 WebSocket 技术
如果你使用了 WebSocket 技术,那么需要在 Nginx 配置当中设置升级你的 HTTP 协议,在 location
块内加入两行:
1 | proxy_set_header Upgrade $http_upgrade; |
否则客户端在尝试使用wss
协议连接到服务器时,会报400错误。
配置Let’s Encrypt
如果你打算使用 Let’s Encrypt 的话,需要首先为获取证书做基本的服务端配置(在这里我们选择 webroot 的方式进行认证):
首先我们需要先建立一个目录放置域名所有权验证文件所需的文件,这里我们以占位符 [Challange folder]
代替。注意,请确保这一目录是可写的。
1 | server { |
之后分别测试配置文件、重新启动 Nginx、安装 Certbot 并开始使用 webroot 方式获取证书(下面的命令需要逐行执行,确保每一行执行成功之后再执行下一行,我的环境是 CentOS 7 所以使用 yum,如果你是 ubuntu 的话可能需要使用 apt-get,Fedora 使用 dnf):
1 | nginx -t |
如果不出意外的话,你已经可以看到成功获得证书的提示信息了,输出信息当中应当会包含证书的存储地址,记下该地址以备一会填写 nginx 信息。一般的,通过 Certbot 生成的证书会被存储在 /etc/letsencrypt/live/[yourdomain]/
或者 /etc/certbot/live/[yourdomain]/
下。
接下来我们添加自动更新:
1 | crontab -e |
在弹出的文本编辑器中,插入下面的语句,并保存退出。
1 | 0 0 * * 3 certbot renew --post-hook "systemctl reload nginx" |
上面这条语句的意思是:每周三晚上十二点的时候为你的证书续期并重启 nginx 服务。
接下来,重新编辑你的 nginx 配置文件:
1 | server { |
最后,使用 nginx -t
测试配置文件书写的正确性,并通过 service nginx restart
重启Nginx服务。
这样,你的应用就部署完成啦(ゝ∀・)b!
番外
http 上不去但是 https 上得去不一定是因为你的 nginx 配置文件有问题,也有可能是因为你的 IP 因为某些不可抗力【哔——】。别问我为什么要提醒你,我才不会告诉你明明上午都没问题下午我的网站用 http 就上不去了呢,哼!我更不会告诉你我为了排查这个「bug」花了一下午呢!哼!(ㆆᴗㆆ)|||
Comments
No comments here,
Why not write something?