如何安全地将 Node 应用程序部署到 Ubuntu 服务器
本博客介绍如何使用 Nginx 将 Node 应用部署到服务器,无论是“VPS”、“VDS”还是“专用服务器”。本文假设您熟悉基本的“Linux”和“git”命令。这适用于运行服务器的任何 Node 应用,无论是“Express”应用、“Next.js”应用、“Remix”应用等。另外需要注意的是,我们将部署应用程序代码;数据库将被分离。
假设
工作流程步骤
1. 保护您的服务器
A. 登录到您的服务器
ssh root@172.172.172.172
系统将提示您提供 root 密码。输入密码后,您将登录到服务器。您应该看到类似以下内容:
root@vm172048:~$
如果是的话,您已经成功以 root 用户身份登录。
B. 服务器强化
现在我们已经进入了机器内部,我们可以开始安装必要的软件包和软件,但在此之前,让我们先升级系统。在终端中输入以下命令:
apt update && apt upgrade -y
现在,所有当前软件包都已更新至最新补丁版本,从而保证系统免受“未修补的漏洞利用”的侵害。
C.创建非Root用户
不建议以 root 用户身份部署,因为 root 用户拥有所有服务器资源的完全访问权限。因此,让我们创建一个名为“admin”的**非 root 用户**,并将其添加到“sudo”组以使用需要 root 权限的命令。
要创建 `sudo` 用户:
useradd -m -s /bin/bash admin
这将创建一个名为“admin”的新用户,您可以使用“groups”命令检查该用户的组。
groups admin
我们将 `admin` 用户添加到 `sudo` 组:
usermod -aG sudo admin
这会将用户添加到“sudo”组,而不会将其从原始“admin”组中删除。
现在让我们为用户**创建密码**:
sudo passwd admin
系统将提示您输入新密码并重新输入。
要**检查密码是否设置正确**,请打开一个新终端并输入以下命令进行检查:
ssh admin@172.172.172.172
系统将提示您输入新密码。输入后,您应该会看到类似以下内容的内容:
admin@vm172048:~$
D.使用 SSH 连接到服务器
不建议使用**密码登录**。您需要使用 SSH(安全外壳)并确保**SSH 是唯一的登录方式**。
如果您是 `git` 用户,则很可能您已经设置了 `ssh key`。如果您还没有 `ssh key`,请使用以下命令在您的**本地机器**上生成新的 SSH 密钥:
ssh-keygen -t ed25519 -C "your_email@example.com" -f ~/.ssh/example
激活 SSH 代理:
eval "$(ssh-agent -s)" && ssh-add ~/.ssh/example
使用 `cat ~/.ssh/example.pub` 复制密钥。登录服务器然后将其粘贴到服务器的 `~/.ssh/authorized_keys` 中:
mkdir ~/.ssh touch ~/.ssh/authorized_keys sudo nano ~/.ssh/authorized_keys
完成所有这些后,您应该能够无需使用密码登录。
E. 在服务器上禁用 Root 和密码登录
要关闭用户名和密码登录,请输入:
sudo nano /etc/ssh/sshd_config
找到这些值并按如下方式设置它们:
Port 1234 # Change the default port (use a number between 1024 and 65535) PermitRootLogin no # Disable root login PasswordAuthentication no # Disable password authentication PubkeyAuthentication yes # Enable public key authentication AuthorizedKeysFile .ssh/authorized_keys # Specify authorized_keys file location AllowUsers admin # Only allow specific users to log in
这将禁止您复制公钥的用户使用除 SSH 之外的所有登录方法。它会停止以 root 身份登录,只允许您指定的用户登录。按“CTRL+S”保存,按“CTRL+X”退出文件编辑器。重新启动 SSH:
sudo service ssh restart
现在尝试以 root 身份登录,看看是否不允许。由于您将默认 SSH 端口从 22 更改为 1234,因此您需要在登录时提及端口。
ssh -p 1234 root@172.172.172.172
由于 root 登录已被禁用,因此这将禁止您登录。要登录,请使用:
ssh -p 1234 admin@172.172.172.172
此外,不言而喻,**您需要妥善保管私钥**,如果丢失了私钥,**您将无法再远程进入**。
F. 防火墙配置
Ubuntu 默认自带 `ufw` 防火墙,如果没有,可以使用以下命令安装:
sudo apt install ufw -y
要查看“ufw”的当前状态,请输入:
sudo ufw status
这将显示防火墙的当前状态。要启用防火墙,请运行以下命令:
sudo ufw enable
首先,运行一些默认策略:
sudo ufw default deny incoming && sudo ufw allow outgoing
现在,由于我们将 SSH 端口更改为“1234”,因此请允许它通过防火墙。除此之外,我们将使用端口 80 和 443 通过 HTTP 和 HTTPS 进行 Web 服务,因此也请允许它们。
sudo ufw allow 1234,80,443
为了进一步提高通过 SSH 进行暴力登录的能力,请使用以下命令:
sudo ufw limit 1234
这会将端口 1234 限制为 30 秒内来自单个 IP 的 6 个连接。如果您错误地打开了任何端口,则可以使用以下命令拒绝连接:
sudo ufw deny
现在,要查看当前状态,请使用:
sudo ufw status verbose
重新启动“ufw”以确保所有规则都已应用:
sudo ufw reload
启用防火墙后,**切勿**在未启用 `ssh` 连接规则的情况下**退出远程服务器连接**。否则,**您将无法登录自己的服务器**。
G.Fail2Ban 配置
Fail2Ban 为 Ubuntu 22.04 提供了保护盾,专门用于阻止对 SSH 和 FTP 等基本服务的未经授权的访问和暴力攻击。要安装“fail2ban”,请使用以下命令:
sudo apt install fail2ban
安装完成后,使用以下命令启动 Fail2ban 服务:
sudo systemctl start fail2ban
要在 Ubuntu 22.04 上启用 Fail2ban 以便它在系统启动时自动启动,请使用:
sudo systemctl enable fail2ban
接下来,我们需要使用以下命令验证 Fail2ban 是否已启动并正常运行:
sudo systemctl status fail2ban
现在让我们配置Fail2ban。主要配置位于`/etc/fail2ban/jail.conf`,但建议创建一个本地配置文件:
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
现在打开“jail.local”文件并调整默认部分中的值:
bantime = 10m findtime = 10m maxretry = 5
Fail2Ban 的工作原理是,在定义的 **查找时间** 内检测到重复失败后,在指定的 **禁止时间** 内禁止某个 IP。**最大重试** 设置决定了禁止 IP 之前允许的失败次数。
现在重新启动 Fail2ban 服务:
sudo systemctl restart fail2ban
要查看哪个 jail 激活了哪个服务,请输入:
sudo fail2ban-client status
如果您已经走到这一步,恭喜您!您已保护好服务器。现在可以部署您的“webApp”了。输入“exit”结束会话。
exit
2.DNS 配置
我们的网站将以域名为人所知,在本例中为“example.com”。为了使域名指向我们的服务器,我们需要在域名提供商端进行一些 DNS 配置。
a. 登录您的域名提供商的网站。
b. 导航到“example.com”,然后管理 DNS 管理。
c.现在更新 IPv4 和 IPv6 地址的“A”和“AAAA”记录。
d. 接下来,更新 `CNAME` 记录以将 `www.example.com` 转发到 `example.com`。
`CNAME` 将子域名映射到另一个域名。
现在可能需要几分钟才能传播到所有 DNS 服务器。要检查“example.com”是否解析为您的主机“IP 地址”,请使用此在线工具检查 DNS 传播:DNS 检查器。
3.部署 Web 应用
要部署,我们需要安装几个软件包。首先,我们将使用“git”从“GitHub”克隆存储库。由于它是一个 Node 应用程序,我们需要在系统上安装“Node”;我将使用 Node 版本 20。我们将使用“Node”附带的“npm”。最后,为了将应用程序作为后台进程进行管理,我们将使用“pm2”。
首先,使用以下命令登录您的服务器:
ssh -p 1234 admin@172.172.172.172
A.安装所有必要的依赖项
a.首先检查安装:
nginx -v node -v npm -v git --version pm2 --version
b.然后更新到最新版本并删除不必要的包:
sudo apt update && sudo apt upgrade -y && sudo apt autoremove -y
c. 安装最新版本的 `git`:
sudo apt install git -y
d. 安装 `Node` 版本 20 及其附带的 `npm`(Node 包管理器):
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo bash - sudo apt-get install -y nodejs
e. 安装 `nginx` Web 服务器:
sudo apt install -y nginx
B.从 GitHub 克隆代码库
我们的代码库将托管在“GitHub”上。我们将使用部署密钥将库克隆到我们的服务器。
a. 首先,生成一个名为“example”的部署密钥:
ssh-keygen -t ed25519 -C "your_email@gmail.com" -f ~/.ssh/example
系统将提示您输入密码;只需按回车键即可。这将在您的 `~/.ssh` 文件夹中生成一对名为 `example.pub` 和 `example` 的公钥-私钥对。
b. 确保 `~/.ssh` 文件夹归 `admin` 所有:
sudo chown -R admin ~/.ssh
c. 将 GitHub 的 SSH 服务器公钥添加到服务器的“known_hosts”文件中:
ssh-keyscan -t ed25519 github.com >> ~/.ssh/known_hosts
d.接下来,将密钥输出到终端后,复制 SSH 公钥:
cat ~/.ssh/example.pub
e. 使用复制的密钥作为 GitHub 中的部署密钥:
f. 使用以下命令将项目从 GitHub Repo 克隆到服务器主目录中:
git clone git@github.com:admin7374/example_app.git
这里,“admin7374”是 GitHub 用户名,“example_app”是我们即将部署的 Node 应用。这将在服务器上克隆代码库。
C.使用 pm2 运行应用程序
现在是时候在后台构建并运行 Node 应用程序了:
a. 导航到项目文件夹:
cd ~/example_app
b.创建一个 `.env` 文件:
touch .env
c. 打开 `.env` 文件并粘贴您的环境变量:
sudo nano .env
`.env` 文件示例:
PORT = 8001 DATABASE_URL = "database_url"
粘贴后,单击“CTRL + S”和“CTRL + X”保存并退出。
d. 在您的 repo 代码中创建一个 `ecosystem.config.cjs` 文件(最好在 GitHub repo 中创建):
touch ecosystem.config.cjs sudo nano ecosystem.config.cjs
然后粘贴下面的代码:
module.exports = { apps : [ { name: "example_app", script: "npm start", port: 8001 // optional, if have port set in app } ] }
上述代码将在端口“8001”上运行 Node 应用;请确保它与应用程序中定义的端口匹配。“script”通常是 Node 应用的运行方式。它假定您的“package.json”中有一个“npm start”脚本来运行构建代码。
e. 接下来,使用以下命令安装必要的 Node 模块:
npm ci
上述命令创建一个“node_modules”文件夹,其中包含运行代码所需的所有包。
f.现在让我们构建代码。输入:
npm run build
上述脚本将使用“package.json”中定义的“build”脚本构建用于分发的代码。
g. 启动时添加 PM2 进程:
sudo pm2 startup
h. 使用 `pm2` 启动 Node App:
pm2 start ecosystem.config.cjs
i. 保存PM2进程:
pm2 save
这将保存在后台继续运行的进程。
j.列出所有在后台运行的 PM2 进程:
pm2 list
k. 如果需要重新加载以进行重新部署,请使用:
pm2 reload example_app
l. 要检查 PM2 进程日志,请使用:
pm2 monit
这将打开一个交互式终端,显示每个进程的日志和元数据。输入“q”退出。
m. 使用以下方法检查应用程序是否正常运行:
curl localhost:8001
如果应用程序正常运行,这应该可以正确输出。
D. 使用 NGINX 提供应用程序
现在是时候使用 Nginx 来最终为应用程序提供服务了。Nginx 是一个强大的 Web 服务器、反向代理和负载均衡器。在本例中,我们将使用 `nginx` 反向代理功能将运行在 `localhost:8001` 上的应用程序提供给互联网。
a. 启动并启用 `nginx`:
sudo systemctl start nginx sudo systemctl enable nginx
b. 验证“nginx”是否已启动并正在运行:
sudo systemctl status nginx
如果一切顺利,输出应该表明 Nginx 服务处于“活动(正在运行)”状态。
c.如果您希望通过 Web 浏览器确认 Nginx 的操作,请导航至:
http://example.com
这应该显示默认的“nginx”页面。
d. 如果没有显示,则 `ufw` 防火墙可能阻止了端口 `80` 和 `443`。要允许它们通过 `ufw` 防火墙,请使用:
sudo ufw allow 'Nginx Full'
e. 与许多服务器软件一样,Nginx 依赖配置文件来决定其行为。首先为您的网站创建一个配置文件:
sudo nano /etc/nginx/sites-available/example.com
f. 在此文件中,输入以下代理传递配置:
server { listen 80; listen [::]:80; server_name example.com www.example.com; location / { proxy_pass http://localhost:8001; # Proxy Params - pass client request information to the proxied server proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # If you need to upload files larger than 1M, use the below directive # client_max_body_size 500M; # Web socket upgrade configuration # Uncomment the following lines if you're using websockets in your app # proxy_http_version 1.1; # proxy_set_header Upgrade $http_upgrade; # proxy_set_header Connection "upgrade"; } # Logging access_log /var/log/nginx/example.com.access.log; error_log /var/log/nginx/example.com.error.log warn; }
代理传递配置直接提供文件服务;它将请求代理到本地应用程序(在本例中,在端口 8001 上运行)。
g. 配置文件创建后,尚未生效。要激活它,您需要创建指向“sites-enabled”目录的符号链接:
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com
将此步骤视为“发布”您的配置,使其生效并准备好处理流量。
h. 上线前测试配置:
sudo nginx -t
然后 Nginx 会解析你的配置并返回反馈。成功表示你的配置没有错误。
i. 上线时间到了。这需要重新加载:
sudo systemctl reload nginx
j.现在检查 Web 浏览器,转到:
http://example.com
k. 我们当前的网站配置通过端口 80 上的 HTTP 提供内容,这些内容未加密。让我们通过 Let's Encrypt 对其进行加密。首先,安装 certbot:
sudo apt update sudo apt install software-properties-common sudo add-apt-repository ppa:certbot/certbot sudo apt update sudo apt install certbot python3-certbot-nginx
l.使用 certbot 生成 SSL 证书:
sudo certbot --nginx -d example.com -d www.example.com
只需按照提示中的说明进行操作即可。您的网站将使用适当的 SSL/TLS 加密证书进行加密。在浏览器中检查您的网站是否已安装。
m. 现在,certbot 在获得新证书时会为您设置自动续订,因此这是一项无需担心的任务。但为了确保它有效,您可以运行:
sudo systemctl status certbot.timer
现在,恭喜你!您已成功使用 Nginx 部署了 Web 应用程序。如果您想优化 Nginx,我建议您阅读这篇文章:基本 Nginx 设置。
至此,我完成了关于**如何使用 Nginx 安全地部署 Node 应用程序**的文档。