介绍
Node.js是一个开源的JavaScript运行时环境,用于轻松构建服务器端和网络应用程序。 该平台在Linux,OS X,FreeBSD和Windows上运行。 Node.js应用程序可以在命令行运行,但我们将专注于将它们作为服务运行,以便在重新引导或故障时自动重新启动,并且可以安全地在生产环境中使用。
在本教程中,我们将介绍如何在单个Ubuntu 16.04服务器上设置一个生产就绪的Node.js环境。 此服务器将运行由PM2管理的Node.js应用程序,并通过Nginx逆向代理为用户提供对应用程序的安全访问。 Nginx服务器将提供HTTPS,使用Let's Encrypt提供的免费证书。
先决条件
本指南假设你有一个Ubuntu 16.04服务器,与非root用户配置的sudo
特权,如中所述的Ubuntu 16.04服务器初始设置指南 。
它还假定您有一个域名,指向服务器的公共IP地址。
让我们开始在你的服务器上安装Node.js运行时。
安装Node.js
我们将安装Node.js的最新当前版本中,使用NodeSource包文件。
首先,您需要安装NodeSource PPA才能访问其内容。 确保你在你的home目录里,并用curl
检索Node.js的6.x的档案安装脚本:
cd ~
curl -sL https://deb.nodesource.com/setup_6.x -o nodesource_setup.sh
您可以检查这个脚本的内容nano
(或者您喜欢的文本编辑器):
nano nodesource_setup.sh
而在运行该脚本sudo
:
sudo bash nodesource_setup.sh
PPA将添加到您的配置中,并且本地包缓存将自动更新。 从nodesource运行安装脚本后,您可以按照上面的方式安装Node.js包:
sudo apt-get install nodejs
该nodejs
包中包含nodejs
二进制以及npm
,所以你不需要安装npm
分开。 但是,为了对一些npm
包工作(如那些需要从源代码编译),您将需要安装build-essential
包:
sudo apt-get install build-essential
Node.js运行时现在已安装,并准备运行应用程序! 让我们编写一个Node.js应用程序。
注意:当从NodeSource PPA安装,Node.js的可执行文件名为nodejs
,而不是node
。
创建Node.js应用程序
我们将编写一个Hello World应用程序,它只是返回的“Hello World”的任何HTTP请求。 这是一个示例应用程序,将帮助您获得您的Node.js设置,您可以替换为您自己的应用程序 - 只是确保您修改您的应用程序以监听相应的IP地址和端口。
Hello World代码
首先,创建并打开您的Node.js应用程序以进行编辑。 在本教程中,我们将使用nano
编辑示例应用程序调用hello.js
:
cd ~
nano hello.js
将以下代码插入到文件中。 如果你愿意,你可以更换高亮度显示端口, 8080
,在这两个位置(一定要使用非管理端口,即1024或更高版本):
#!/usr/bin/env nodejs
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(8080, 'localhost');
console.log('Server running at http://localhost:8080/');
现在保存并退出。
这Node.js的应用程序只监听指定的地址( localhost
)和端口( 8080
),和一个返回“Hello World”的200
HTTP成功代码。 由于我们监听localhost,远程客户端将无法连接到我们的应用程序。
测试应用程序
为了测试你的应用程序,标志hello.js
可执行文件:
chmod +x ./hello.js
并运行它像这样:
./hello.js
OutputServer running at http://localhost:8080/
注:以这种方式运行的Node.js应用程序会阻止其他命令,直到应用程序按Ctrl-C杀害。
为了测试应用程序,您的服务器上打开另一个终端会话,并与连接到本地主机 curl
:
curl http://localhost:8080
如果看到以下输出,应用程序正常工作并侦听正确的地址和端口:
OutputHello World
如果没有看到正确的输出,请确保您的Node.js应用程序正在运行,并配置为监听正确的地址和端口。
一旦你确定它的工作,杀死应用程序(如果您还没有),按Ctrl + C。
安装PM2
现在我们将安装PM2,它是Node.js应用程序的进程管理器。 PM2提供了一种简单的方法来管理和守护应用程序(在后台作为服务运行它们)。
我们将使用npm
,用于节点模块的软件包管理器,与Node.js的安装,到我们的服务器上安装PM2。 使用此命令安装PM2:
sudo npm install -g pm2
该-g
选项告诉npm
在全球范围内安装模块,所以它的系统范围内可用。
使用PM2管理应用程序
PM2简单易用。 我们将介绍PM2的几个基本用途。
启动应用程序
你会想要做的第一件事就是使用pm2 start
命令来运行你的应用程序, hello.js
,在后台:
pm2 start hello.js
这也将您的应用程序添加到PM2的进程列表,这是每次启动应用程序时输出的:
Output[PM2] Spawning PM2 daemon
[PM2] PM2 Successfully daemonized
[PM2] Starting hello.js in fork_mode (1 instance)
[PM2] Done.
┌──────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────────────┬──────────┐
│ App name │ id │ mode │ pid │ status │ restart │ uptime │ memory │ watching │
├──────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────────────┼──────────┤
│ hello │ 0 │ fork │ 3524 │ online │ 0 │ 0s │ 21.566 MB │ disabled │
└──────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────────────┴──────────┘
Use `pm2 show <id|name>` to get more details about an app
正如你所看到的,PM2自动分配一个应用程序名称 (基于文件名,没有.js
扩展名)和PM2 ID。 PM2还维护的其它信息,如进程的PID,其当前状态,和存储器使用率。
在PM2下运行的应用程序将在应用程序崩溃或被终止时自动重新启动,但需要执行额外的步骤才能在系统启动(启动或重新引导)时启动应用程序。 幸运的是,PM2提供了一种简单的方法来做到这一点, startup
子命令。
该startup
子产生并配置启动脚本启动PM2和管理流程上的服务器引导。 你还必须指定要运行的平台,这是ubuntu
,在我们的例子:
pm2 startup systemd
结果输出的最后一行将包含一个必须使用超级用户权限运行的命令:
Output[PM2] You have to run this command as root. Execute the following command:
sudo su -c "env PATH=$PATH:/usr/bin pm2 startup systemd -u sammy --hp /home/sammy"
运行生成的命令(类似于上面的高亮输出,但与您的用户名,而不是sammy
)来设置PM2为什么要在开机启动(使用您自己的输出命令):
sudo su -c "env PATH=$PATH:/usr/bin pm2 startup systemd -u sammy --hp /home/sammy"
这将创建一个运行systemd 单元 pm2
上引导用户。 这pm2
例如,反过来,运行hello.js
。 您可以检查与systemd单元的状态systemctl
:
systemctl status pm2
对于systemd的详细介绍,请参见Systemd要领:用服务,单位和学报工作 。
其他PM2用法(可选)
PM2提供了许多子命令,允许您管理或查找有关应用程序的信息。 请注意,运行pm2
不带任何参数将显示一个帮助页面,包括用法示例,涵盖PM2使用在除本节中的更多细节。
停止使用此命令(指定PM2的应用程序App name
或id
):
pm2 stop app_name_or_id
重新启动使用此命令(指定PM2的应用程序App name
或id
):
pm2 restart app_name_or_id
目前由PM2管理的应用程序列表也可以抬头与list
子命令:
pm2 list
有关特定应用程序的更多信息,可以通过使用发现info
子(指定PM2 应用程序名称或ID):
pm2 info example
该PM2进程监视器可以与拉升monit
子命令。 这将显示应用程序状态,CPU和内存使用情况:
pm2 monit
现在你的Node.js应用程序正在运行,并由PM2管理,让我们设置反向代理。
将Nginx设置为反向代理服务器
现在,您的应用程序正在运行,并监听本地主机 ,你需要设置为你的用户访问它的方法。 我们将为此设置一个Nginx Web服务器作为反向代理。 本教程将从头开始设置一个Nginx服务器。 如果你已经有一个Nginx的服务器设置,您可以将刚才复制location
块到您选择的服务器模块(确保位置不与任何Web服务器的现有内容的冲突)。
首先,使用apt-get安装Nginx:
sudo apt-get install nginx
现在打开默认服务器块配置文件进行编辑:
sudo nano /etc/nginx/sites-available/default
删除文件中的所有内容并插入以下配置。 一定要代替你自己的域名为server_name
指令。 此外,更改端口( 8080
),如果你的应用程序设置为监听在不同的端口:
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
这将配置服务器以响应其根目录中的请求。 假设我们的服务器可在example.com
,访问http://example.com/
通过Web浏览器将请求发送到hello.js
,侦听端口8080
的本地主机 。
您可以添加其他location
的块到同一服务器模块能提供访问其他应用程序在同一台服务器上。 例如,如果您还运行在端口另一个应用程序的Node.js 8081
,您可以通过添加此位置区块允许访问它http://example.com/app2
:
location /app2 {
proxy_pass http://localhost:8081;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
为应用程序完成添加位置块后,保存并退出。
确保您没有通过键入以下语法错误:
sudo nginx -t
接下来,重启Nginx:
sudo systemctl restart nginx
接下来,允许通过防火墙到Nginx的流量,如果你启用:
sudo ufw allow 'Nginx Full'
假设你的Node.js应用程序正在运行,你的应用程序和Nginx配置是正确的,你现在应该能够通过Nginx反向代理访问你的应用程序。 尝试通过访问您的服务器的URL(其公共IP地址或域名)。
现在您可以访问您的应用程序,我们将使用Let's Encrypt通过HTTPS保护您的应用程序的连接。
安装让我们加密和依赖
Let's Encrypt是一个新的证书颁发机构,提供了一种获取免费TLS / SSL证书的简单方法。
您必须拥有或控制您希望使用证书的注册域名。 如果您还没有注册域名,您可以向其中一个域名注册商(例如Namecheap,GoDaddy等)注册一个域名。
如果你还没有准备好,一定要创建一条A记录指向你自己的域名服务器的公网IP地址。 这是必需的,因为Let's Encrypt验证您拥有它为其颁发证书的域。 例如,如果你想获得一个证书example.com
,该域必须解析到服务器的验证过程工作。
有关此过程的详细信息,请参阅如何设置主机名与DigitalOcean和怎么点从常见的域名注册商DigitalOcean域名服务器 。
虽然咱们加密项目已更名为他们的客户certbot
,包在Ubuntu 16.04版本库的名称就是letsencrypt
。 这个包将完全满足我们的需要。
要安装软件包,请键入:
sudo apt-get install letsencrypt
该letsencrypt
现在客户应准备好您的服务器上使用。
检索初始证书
由于nginx
是已经在端口80上运行,并且让我们的加密客户端需要为了验证域名所有权的这个端口,停止nginx
暂时:
sudo systemctl stop nginx
运行letsencrypt
的独立插件:
sudo letsencrypt certonly --standalone
系统会提示您回答几个问题,包括您的电子邮件地址,同意服务条款以及证书的域名。 完成后,您会收到类似以下内容的注释:
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/your_domain_name/fullchain.pem. Your cert will expire
on 2016-08-10. To obtain a new version of the certificate in the
future, simply run Let's Encrypt again.
- If you like Let's Encrypt, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
注意证书的路径和到期日期,在示例输出中突出显示。 您的证书文件现在应该在现有/etc/letsencrypt/ your_domain_name /
。
为Nginx配置HTTPS
你需要添加一些细节到你的Nginx配置。 开放/etc/nginx/sites-enabled/default
在nano
(或您选择的编辑器):
sudo nano /etc/nginx/sites-enabled/default
将其内容替换为以下内容:
# HTTP - redirect all requests to HTTPS:
server {
listen 80;
listen [::]:80 default_server ipv6only=on;
return 301 https://$host$request_uri;
}
# HTTPS - proxy requests on to local Node.js app:
server {
listen 443;
server_name your_domain_name;
ssl on;
# Use certificate and key provided by Let's Encrypt:
ssl_certificate /etc/letsencrypt/live/your_domain_name/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your_domain_name/privkey.pem;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
# Pass requests for / to localhost:8080:
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://localhost:8080/;
proxy_ssl_session_reuse off;
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
proxy_redirect off;
}
}
退出编辑器并保存文件。
键入以下内容以检查语法错误的配置:
sudo nginx -t
当没有检测到错误时,再次启动Nginx:
sudo systemctl start nginx
您可以通过访问测试新的证书和Nginx的配置http:// your_domain_name /
在浏览器中。 您应该被重定向到https:// your_domain_name /
,没有任何安全错误,并看到的“Hello World”你的Node.js应用程序打印。
设置让我们加密自动续订
警告:您可以安全地完成本指南,而不必担心证书更新,但你将需要解决它的任何长寿命的生产环境。
您可能已经注意到,您的Let's Encrypt证书将在90天后到期。 这是Let's Encrypt方法的一个故意功能,旨在最小化受损证书在出现问题时可以存在的时间。
Let's Encrypt客户端可以自动更新您的证书,但同时您将不得不手动重复证书检索过程,或使用预定的脚本为您处理它。 自动化这一过程的详细信息在如何使用让我们在Ubuntu 16.04加密安全Nginx的 ,特别是在部分设置自动续约 。
结论
恭喜! 现在,您的Node.js应用程序运行在Ubuntu 16.04服务器上的Nginx逆向代理之后。 这种逆向代理设置足够灵活,可以让您的用户访问您想要共享的其他应用程序或静态Web内容。 祝你运行你的Node.js开发!