📝
VPS

Strapi 是一个建立在 Node.js 上的开源无头 CMS,使团队能够通过 REST 或 GraphQL API 管理内容。本指南涵盖在运行 Ubuntu 22.04 LTS 的 VPS 上部署 Strapi,包括反向代理、HTTPS 和进程管理的生产环境配置。

简而言之:Strapi 是一个基于 Node.js 的无头 CMS,将内容管理与前端展现分离。我们将安装 Node.js、创建 Strapi 项目、使用 PM2 实现自动重启、配置 Nginx 反向代理、通过 Let's Encrypt 启用 HTTPS,并为生产环境强化管理面板安全性。

什么是 Strapi 及为什么选择无头 CMS

传统 CMS(如 WordPress)将后端(内容管理)与前端(内容呈现)紧耦合。无头 CMS 将两者解耦:

无头 CMS 的主要优势:

前置要求

小贴士:512 MB RAM 可用于开发或低流量的暂存环境;生产环境有多个 API 消费者时应有 1-2 GB 内存以避免交换。通过 free -hpm2 monit 监控实际使用情况。

步骤 1:安装 Node.js

Strapi 需要 Node.js 18 或更高版本。使用 nvm(Node 版本管理器)管理多个 Node 版本:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
source ~/.bashrc
nvm --version

安装 Node.js LTS(推荐版本 20 或 22):

nvm install 20
nvm use 20
node --version
npm --version

将 Node.js 20 设置为默认版本:

nvm alias default 20

步骤 2:创建 Strapi 项目

使用官方启动器引导新的 Strapi 项目:

npx create-strapi-app@latest my-strapi-cms --quickstart

这会创建一个目录结构:

my-strapi-cms/
├── api/           # 插件和 API 扩展
├── config/        # 配置文件
├── database/      # SQLite 数据库(默认)
├── public/        # 提供给公众的静态文件
├── src/           # 源代码
├── package.json
└── .env           # 环境变量

--quickstart 标志使用 SQLite 并启动开发服务器;我们将在下面重新配置用于生产。

步骤 3:设置数据库和环境变量

SQLite vs 生产数据库:

数据库 用途 优点 缺点
SQLite 开发 无需设置,基于文件,轻量 写入时锁定,并发性能差
PostgreSQL 生产 稳健、快速、适合并发工作负载 需要单独的数据库服务器
MySQL/MariaDB 生产 广泛可用,性能良好 需要单独的数据库服务器

本指南使用 PostgreSQL(推荐):

sudo apt update
sudo apt install postgresql postgresql-contrib -y
sudo systemctl start postgresql
sudo systemctl enable postgresql

创建数据库用户和数据库:

sudo -u postgres psql
CREATE USER strapi WITH PASSWORD 'your_secure_password';
CREATE DATABASE strapi OWNER strapi;
\q

注意:使用强密码:至少 16 个字符,包含大小写字母、数字和特殊字符。将其安全地存储在密码管理器中。永远不要将密码提交到版本控制。

更新 Strapi 项目中的 .env 文件:

nano .env

配置用于生产环境和 PostgreSQL:

NODE_ENV=production
DATABASE_CLIENT=postgres
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_NAME=strapi
DATABASE_USERNAME=strapi
DATABASE_PASSWORD=your_secure_password
JWT_SECRET=your_jwt_secret_here
API_TOKEN_SALT=your_api_token_salt_here
ADMIN_JWT_SECRET=your_admin_jwt_secret_here

为 JWT 秘钥生成安全的随机字符串:

openssl rand -base64 24

步骤 4:为生产环境构建 Strapi

编译 TypeScript、优化资源并为生产环境进行打包:

npm run build

这会创建一个包含优化后代码的 dist/ 目录。构建时间通常为 2-5 分钟,具体取决于 VPS 资源。

步骤 5:安装和配置 PM2

PM2 是一个进程管理器,可保持 Strapi 运行,在故障时自动重启,并在服务器重启后存活:

npm install -g pm2

创建 ecosystem.config.js 文件定义 PM2 行为:

cat > ecosystem.config.js << 'EOF'
module.exports = {
  apps: [{
    name: 'strapi',
    script: './node_modules/.bin/strapi',
    args: 'develop',
    env: {
      NODE_ENV: 'production',
      DATABASE_CLIENT: 'postgres',
      DATABASE_HOST: 'localhost',
      DATABASE_PORT: 5432,
      DATABASE_NAME: 'strapi',
      DATABASE_USERNAME: 'strapi',
      DATABASE_PASSWORD: 'your_secure_password'
    },
    watch: false,
    max_memory_restart: '1024M',
    log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
    error_file: './logs/err.log',
    out_file: './logs/out.log',
    instances: 1
  }]
};
EOF

用 PM2 在生产模式下启动 Strapi:

pm2 start ecosystem.config.js --env production
pm2 save
pm2 startup

验证 Strapi 正在运行:

pm2 logs strapi
pm2 monit

使用 pm2 monit 实时监控 CPU 和内存;按 q 退出。

步骤 6:配置 Nginx 作为反向代理

Nginx 将流量从端口 80/443 代理到 Strapi 的本地端口 1337,处理 SSL 终止并提高性能:

sudo apt install nginx -y
sudo systemctl start nginx
sudo systemctl enable nginx

为 Strapi 创建 Nginx 配置文件:

sudo nano /etc/nginx/sites-available/strapi

添加此配置:

upstream strapi {
  server 127.0.0.1:1337;
}

server {
  listen 80;
  server_name yourdomain.com;
  
  location / {
    proxy_pass http://strapi;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    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;
    proxy_redirect off;
    proxy_buffering off;
  }
}

启用该站点并测试 Nginx 语法:

sudo ln -s /etc/nginx/sites-available/strapi /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx

小贴士:yourdomain.com 替换为实际域名,并确保 DNS A 记录指向 VPS IP 地址。使用 nslookup yourdomain.com 验证。

步骤 7:使用 Let's Encrypt 启用 HTTPS

安装 Certbot 和 Nginx 插件:

sudo apt install certbot python3-certbot-nginx -y

请求免费的 SSL 证书并自动更新 Nginx:

sudo certbot --nginx -d yourdomain.com

回答提示;Certbot 会自动更新 Nginx 配置并启用 HTTPS。

启用自动证书续期:

sudo systemctl start certbot.timer
sudo systemctl enable certbot.timer

验证 HTTPS 是否正常工作:

curl -I https://yourdomain.com

步骤 8:安全加固和性能调优

管理面板安全:

防火墙配置(ufw):

sudo ufw enable
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp      # SSH
sudo ufw allow 80/tcp      # HTTP
sudo ufw allow 443/tcp     # HTTPS

性能最佳实践:

注意:永远不要公开 .env 文件。配置 Nginx 拒绝访问点文件(以句点开头的文件),确保它们不在公开目录中。同时保持 Git 存储库为私密,并在 .gitignore 中排除 .env

内容类型构建器与内容架构设计

Strapi 运行后,开发团队的核心工作是通过管理面板的内容类型构建器(Content-Type Builder)设计"内容类型"——本质上是在不编写原始 SQL 的情况下设计数据库表。Strapi 将内容类型分为两种:集合类型(Collection Type)用于可重复的记录,例如博客文章、产品或客户评价;单一类型(Single Type)用于固定的一次性数据,例如"关于我们"页面或首页设置。

每个内容类型由多种字段类型构建而成:文本、富文本、数字、布尔值、日期、媒体(用于图片/文件上传)、关系(链接到另一个内容类型,例如一篇文章链接到一位作者),以及组件(可重复使用的字段组,例如在多个页面中共享的 SEO 元数据)。尽早正确设计架构可以减少未来的迁移麻烦——在存在大量真实数据后重新构建内容类型可能会损坏现有记录或需要手动数据迁移。

小贴士:在生产环境创建内容类型之前,先在开发环境中原型设计,并导出架构文件(Strapi 将架构存储在 src/api/*/content-types/*/schema.json)提交到 Git。这让您的团队可以像审查常规代码一样通过 pull request 审查架构变更。

安全升级到新的 Strapi 版本

Strapi 会定期发布主要版本,这些版本有时会包含影响您的 API 或已安装插件的破坏性更改。在生产环境升级之前,请始终遵循此流程:首先,使用 pg_dump 备份整个 PostgreSQL 数据库,并单独备份媒体上传文件夹。其次,在触及生产环境之前,始终在与生产数据高度相似的暂存环境中测试升级。第三,阅读 Strapi 的官方迁移指南,因为每个主要版本通常都包含迁移插件或已更改 API 的具体说明。

准备好升级生产环境时,如果您的网站流量较大,请启用维护模式或提前通知用户。然后运行 npm install @strapi/strapi@latest,接着运行 npm run build 重新编译,并使用 pm2 restart strapi 重启 PM2 进程。升级后立即使用 pm2 logs strapi --lines 100 检查日志,查看是否有尚不支持新版本的插件产生的错误。如果遇到无法解决的问题,您可以立即回滚到数据库备份和之前的代码库版本——这正是为什么升级前备份是绝不应跳过的步骤。

定期备份 Strapi

除了在版本升级前备份之外,还应为生产环境设置定期自动备份计划,因为团队每天创建的内容非常宝贵,一旦服务器出现故障将很难恢复。需要备份的主要有两部分:保存所有内容的 PostgreSQL 数据库,以及保存用户上传的图片和文档的媒体上传文件夹。使用 pg_dump -U strapi strapi > backup-$(date +%Y%m%d).sql 备份数据库,最好设置为每晚运行的 cron 任务,然后将备份文件复制到服务器之外——云存储或第二台 VPS——以防止主服务器完全故障。

对于媒体上传文件夹,可以使用 rsynctar 定期备份,或者为了更高的可靠性,考虑将媒体存储从本地磁盘迁移到兼容 S3 的对象存储。Strapi 通过其上传提供程序插件系统支持这一点,将媒体文件与任何单一服务器解耦,同时减少主 VPS 上的磁盘 I/O 负载。

总结

现在您拥有一个生产就绪的 Strapi 部署:通过 nvm 安装的 Node.js(20 LTS 版本)、具有 PostgreSQL 数据库的 Strapi 项目、使用自动重启管理 Strapi 进程的 PM2、端口 80/443 上的 Nginx 反向代理、通过 Let's Encrypt 的 HTTPS 和自动续期、防火墙加固和强管理员凭证。

您的 Strapi 管理面板可在 https://yourdomain.com/admin 访问,前端应用可从任何语言或框架使用 REST/GraphQL API。使用 pm2 logs strapi 监控日志,使用 pm2 monit 跟踪资源使用情况,以确保稳定运行。

常见问题 (FAQ)

为什么使用 PM2 而不是直接运行 Strapi?

PM2 监控 Strapi 进程,如果崩溃或 VPS 重启,会自动重启。它还提供集中日志记录和资源监控,减少生产环境中的手动干预需求。

部署后可以从 SQLite 迁移到 PostgreSQL 吗?

可以,但需要从 SQLite 导出数据并导入到 PostgreSQL。Strapi 提供迁移指南。在部署到生产前设置目标数据库会更简单。

如果 Strapi 进程消耗过多内存,PM2 重启了怎么办?

在 ecosystem.config.js 中增加 max_memory_restart 阈值,或升级 VPS 到更多内存。还应检查自定义插件或 API 扩展中的内存泄漏,并优化数据库查询。

Strapi 需要 CDN 吗?

对于 API 本身,CDN 缓存有限,因为响应是动态的。但 CDN 对提供静态资源(图像、CSS、JS)很有益处。配置前端使用 CDN 提供这些资源,而不是 Strapi API。

立即开始使用 AsiaGB VPS

AsiaGB VPS 全系列采用 SSD 存储,可选择泰国或新加坡数据中心,并提供完整的 Root 权限,Linux 系统每月低至 500 泰铢起,由泰语技术团队提供支持。

查看 VPS 套餐

查看泰国VPS主机全部套餐 →