在树莓派上自托管 Node.js 网站

对于许多开发者来说,自托管的吸引力不仅在于成本,更在于控制权。虽然 Vercel 或 Netlify 等平台提供无缝部署,但有时特定的技术需求——例如需要使用旧版动态库或希望完全拥有运行环境——会使自建服务器成为更好的选择。

使用树莓派作为 Web 服务器是学习网络、服务器管理和部署流水线细节的绝佳方式。本指南概述了在树莓派上托管基于 Node.js 的网站(例如使用 Astro 或 Svelte 构建的站点)的简化流程。

架构:从路由器到浏览器

要让网站能够从家庭网络对外部世界访问,需要在本地私有 IP 与面向公网的 IP 地址之间搭建桥梁。

1. 端口转发与反向代理

第一步是配置路由器,将进入的流量转发到树莓派的特定内部 IP 地址。由于路由器界面差异很大,这一步需要查阅具体硬件的文档。

流量到达树莓派后,需要一种方式来处理请求并管理 SSL 证书。Caddy 是强烈推荐的工具,因为它会自动处理 HTTPS。下面是一个针对 Astro 站点的典型 Caddyfile 配置:

m4rt.nl {
    root * /home/mart/Documents/m4rt.nl
    file_server
    reverse_proxy localhost:4321
}

在此配置中,Caddy 直接提供静态文件,并将请求代理到运行在 4321 端口的 Node.js 进程。

2. DNS 配置

服务器配置完成后,需要将域名指向家庭网络。这可以通过在 DNS 提供商的设置中添加 A 记录 来实现,将你的域名(例如 yoursite.com)映射到 ISP 提供的公网 IP 地址。

管理应用生命周期

每次修改后手动运行构建脚本效率低下。要构建生产就绪的环境,需要使用进程管理器和部署流水线。

使用 PM2 进行进程管理

在部署 Node.js 应用时,不能仅在终端会话中运行启动命令,因为会话关闭后进程会终止。PM2 是一款生产级进程管理器,可让应用在后台保持运行,并在崩溃时自动重启。

运行 npm run build 后,可以使用以下方式启动入口文件: pm2 run entry.mjs

使用 GitHub Actions 自动化部署

为了模拟现代云平台的 “push-to-deploy” 体验,可以使用 GitHub Actions 实现 CI/CD 流水线。通过创建工作流文件(例如 .github/workflows/update_server.yml),每次向仓库推送代码时,都可以通过 SSH 触发远程更新。

使用 appleboy/ssh-action,工作流可以通过存放主机 IP 和密码的 secret 安全地连接到树莓派,然后执行本地 shell 脚本来处理更新。

更新脚本

一个健壮的更新脚本应能够处理多个项目,并确保拉取并构建最新代码。此类脚本的示例逻辑包括:

  1. 遍历基目录下的子目录。
  2. 检查是否存在 .git 文件夹,以执行 git pull
  3. 通过 package.json 判断 Node.js 项目,并使用特定端口运行构建命令。
  4. 重启所有 PM2 进程以应用更改。

安全考虑与替代方案

虽然端口转发是让站点快速上线的方式,但它会将家庭网络的端口暴露给公共互联网,可能带来安全风险。

正如社区成员在相关讨论中指出的,打洞穿透家庭防火墙可能存在风险。更安全的替代方案是使用 Cloudflare Tunnel。隧道在你的服务器与 Cloudflare 网络之间建立安全的仅出站连接,无需在路由器上打开端口,并且可以隐藏家庭的公网 IP。

通过将树莓派与 Caddy、PM2 和 GitHub Actions 等工具结合,开发者可以在客厅内构建一个全自动、专业级的托管环境。

Sources