Files
Jog/doc/jog-system-deployment-checklist.md
2026-05-17 19:27:45 +08:00

285 lines
19 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Jog System 服务器部署清单
> 适用版本:Jog System v1.0.0
> 后端:Spring Boot 3.4.5 + Java 21
> 前端:Vue 3 + Vite 6(生产构建产物输出至 `jog-admin/src/main/resources/static`,与后端 jar 一体化部署)
> 状态图例:✅ 已完成 ☐ 未完成 ⚠️ 需注意
> **目标服务器**4 核 CPU / 4 GB 内存 / 40 GB 系统盘 / Debian 13.2 (trixie) 64bit
---
## 0. 总体进度
| # | 阶段 | 状态 | 实际使用 |
|:---:|:---|:---:|:---|
| 1 | 服务器基础环境 | ☐ | Debian 13.2 64bit / 4C4G / 40GB |
| 2 | 运行时与构建工具 | 部分(仅 JDK) | JDK 21`openjdk-21-jdk` / Temurin 21),建议本地构建后只上传 jar |
| 3 | 中间件(MySQL / Redis | ☐ | 本机部署 MySQL 8 + Redis 7(受 4GB 内存约束,需调小内存上限) |
| 4 | 邮件服务(SMTP) | ☐ | 使用第三方 SMTP(不在本机部署) |
| 5 | 应用配置与敏感信息 | ☐ | 启用 `application-prod.yml` + 环境变量注入 |
| 6 | 代码拉取与构建 | ☐ | **本地构建**,仅上传 jar(节省服务器内存与磁盘) |
| 7 | 应用部署与启动 | ☐ | systemd 守护,部署目录 `/opt/jog/` |
| 8 | 反向代理与 HTTPS | ☐ | Nginx + Let's Encryptcertbot |
| 9 | 防火墙与安全加固 | ☐ | nftables/ufw + fail2ban |
| 10 | 监控、日志与备份 | ☐ | 轻量方案:journald + mysqldump 定时任务 |
| 11 | 上线后验证 | ☐ | — |
---
## 1. 服务器基础环境
| # | 项目 | 推荐配置 / 说明 | 状态 | 实际使用 |
|:---:|:---|:---|:---:|:---|
| 1.1 | 操作系统 | Linux x86_64(推荐 Ubuntu 22.04 LTS / CentOS Stream 9 / Rocky Linux 9 | ☐ | **Debian 13.2 (trixie) 64bit** ✅ |
| 1.2 | 服务器规格 | 最低 2C4G,推荐 4C8G,系统盘 ≥ 40GB | ☐ | **4 核 / 4 GB 内存 / 40 GB 系统盘** ⚠️ 仅达最低标准,内存需精细分配(应用 ≤ 1.5G、MySQL ≤ 1G、Redis ≤ 256M |
| 1.3 | 时区与时间同步 | 设置为 `Asia/Shanghai`,启用 chronyd / systemd-timesyncd | ☐ | `timedatectl set-timezone Asia/Shanghai`Debian 13 默认启用 `systemd-timesyncd` |
| 1.4 | 主机名与 hosts | 设置规范主机名,必要时配置内网 hosts | ☐ | `hostnamectl set-hostname jog-prod` |
| 1.5 | 部署用户 | 创建非 root 部署用户(如 `deploy`),并配置 sudo / SSH 密钥登录 | ☐ | `adduser deploy && usermod -aG sudo deploy`,仅密钥登录 |
| 1.6 | 关闭 root 密码登录 | `/etc/ssh/sshd_config``PermitRootLogin no` + `PasswordAuthentication no` | ☐ | 修改后 `systemctl restart ssh` |
| 1.7 | 系统更新 | `apt update && apt upgrade -y``dnf update -y` | ☐ | Debian 13 使用 `apt update && apt upgrade -y` |
| 1.8 | 常用工具安装 | `git`, `curl`, `wget`, `unzip`, `vim`, `net-tools`, `lsof` | ☐ | `apt install -y git curl wget unzip vim net-tools lsof ca-certificates gnupg` |
| 1.9 | 文件描述符限制 | `/etc/security/limits.conf``nofile 65535` | ☐ | systemd 服务同步配置 `LimitNOFILE=65535` |
---
## 2. 运行时与构建工具
| # | 项目 | 版本要求 | 验证命令 | 状态 | 实际使用 |
|:---:|:---|:---|:---|:---:|:---|
| 2.1 | **JDK** | **21(项目 `pom.xml` 中 `java.version=21`** | `java -version` | ✅ | Debian 13 官方仓库可直接 `apt install -y openjdk-21-jdk`;或使用 Adoptium Temurin 21 |
| 2.2 | `JAVA_HOME` 环境变量 | 指向 JDK 21 安装路径 | `echo $JAVA_HOME` | ☐ | `/usr/lib/jvm/java-21-openjdk-amd64`,写入 `/etc/profile.d/jdk.sh` |
| 2.3 | Maven | 3.9+ | `mvn -v` | ☐ | **服务器不安装**,本地构建 |
| 2.4 | Maven 镜像源 | `~/.m2/settings.xml` 配置阿里云镜像(加速依赖下载) | — | ☐ | 本地开发机配置阿里云镜像即可 |
| 2.5 | Node.js | 18.x 或更高(推荐 20 LTS | `node -v` | ☐ | **服务器不安装**,本地构建 |
| 2.6 | npm / pnpm | 与 Node 配套 | `npm -v` | ☐ | 本地使用 npm 10+ |
| 2.7 | npm 镜像源 | `npm config set registry https://registry.npmmirror.com` | — | ☐ | 本地配置 |
| 2.8 | Git | 任意现代版本 | `git --version` | ☐ | `apt install -y git`(仅在需要时) |
> ⚠️ 4GB 内存机器建议**采用本地构建后只上传 jar 与静态资源**,服务器不安装 Maven / Node,可显著降低内存与磁盘占用。
---
## 3. 中间件部署
### 3.1 MySQL 8.0+
| # | 项目 | 说明 | 状态 | 实际使用 |
|:---:|:---|:---|:---:|:---|
| 3.1.1 | 安装 MySQL | 8.0+,与 `mysql-connector-j` 兼容 | ☐ | Debian 13 官方仓库**不带 mysql-server**,使用 MySQL 官方 APT 仓库安装 8.0 或改用 MariaDB 11;推荐:从 `https://dev.mysql.com/downloads/repo/apt/` 安装 mysql-server 8.0 |
| 3.1.2 | 启用并设置开机自启 | `systemctl enable --now mysqld` | ☐ | `systemctl enable --now mysql` |
| 3.1.3 | 设置 root 强密码 | 禁止使用默认密码 `root` | ☐ | `mysql_secure_installation` |
| 3.1.4 | 创建数据库 | `CREATE DATABASE jog_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;` | ☐ | 库名固定 `jog_db` |
| 3.1.5 | 创建业务账号 | 创建 `jog` 账户并仅授予 `jog_db` 权限(避免使用 root) | ☐ | 账号 `jog`,密码经环境变量 `JOG_DB_PASSWORD` 注入 |
| 3.1.6 | 字符集与时区 | `character_set_server=utf8mb4``default_time_zone='+08:00'` | ☐ | 写入 `/etc/mysql/mysql.conf.d/jog.cnf` |
| 3.1.7 | bind-address | 仅监听内网或 `127.0.0.1`,不对公网开放 | ☐ | `bind-address = 127.0.0.1` |
| 3.1.8 | Flyway 自动迁移 | 启动时自动执行 `db/migration/V1__init_schema.sql``V2__init_data.sql` | ☐ | 应用首次启动自动完成 |
| 3.1.9 | 默认管理员账号 | 首次登录后立即修改 `admin / Admin@123` 密码 | ☐ | 首次登录后立即修改 |
| 3.1.10 | **内存调优(4GB 机器关键)** | 默认配置可能占用 ≥ 400MB | ☐ | `innodb_buffer_pool_size=512M``max_connections=80`、关闭 performance_schema |
### 3.2 Redis 7.2.x
| # | 项目 | 说明 | 状态 | 实际使用 |
|:---:|:---|:---|:---:|:---|
| 3.2.1 | 安装 Redis | 7.2.x | ☐ | Debian 13 官方仓库提供 Redis 7.x`apt install -y redis-server` |
| 3.2.2 | 设置访问密码 | `requirepass` 配置强密码 | ☐ | 强密码经环境变量 `JOG_REDIS_PASSWORD` 注入并写入 `/etc/redis/redis.conf` |
| 3.2.3 | 绑定地址 | `bind 127.0.0.1` 或内网地址,禁用公网访问 | ☐ | `bind 127.0.0.1` + `protected-mode yes` |
| 3.2.4 | 持久化策略 | 按需启用 RDB / AOF | ☐ | 仅启用 RDB`save 900 1 / 300 10 / 60 10000`),降低磁盘 IO |
| 3.2.5 | maxmemory 与淘汰策略 | 根据服务器内存合理设置 | ☐ | **`maxmemory 256mb`**、`maxmemory-policy allkeys-lru`4GB 机器) |
| 3.2.6 | 开机自启 | `systemctl enable --now redis` | ☐ | `systemctl enable --now redis-server` |
> ⚠️ 当前 `application.yml` 中 Redis 未配置密码,部署到服务器前需在配置中追加 `password` 字段。
---
## 4. 邮件服务(SMTP
| # | 项目 | 说明 | 状态 | 实际使用 |
|:---:|:---|:---|:---:|:---|
| 4.1 | SMTP 服务商 | 阿里云邮推 / 腾讯企业邮 / Gmail / 163 等 | ☐ | 待选用第三方 SMTP(不在本机部署,节省内存) |
| 4.2 | 发件账号与授权码 | 替换 `application.yml``your-mail-password` 占位 | ☐ | 通过环境变量 `JOG_MAIL_PASSWORD` 注入 |
| 4.3 | Host / Port | 替换 `smtp.example.com:587` 为真实地址 | ☐ | 待填入服务商提供的 host/port |
| 4.4 | TLS / SSL | `starttls.enable=true` 或改用 465 + ssl | ☐ | 推荐 465 + SSL |
| 4.5 | 测试发信 | 使用注册流程或独立脚本验证 | ☐ | 通过注册流程验证 |
---
## 5. 应用配置与敏感信息
> 文件位置:`jog-admin/src/main/resources/application.yml`
> 推荐生产环境使用 `application-prod.yml` + `--spring.profiles.active=prod`,并通过环境变量注入密钥。
| # | 配置项 | 当前值 / 风险 | 生产应做 | 状态 | 实际使用 |
|:---:|:---|:---|:---|:---:|:---|
| 5.1 | `server.port` | 8080 | 保持或调整,并与 Nginx 后端一致 | ☐ | 保持 `8080`(仅本机访问) |
| 5.2 | `spring.datasource.url` | `localhost:3306/jog_db` | 改为真实数据库地址 | ☐ | `jdbc:mysql://127.0.0.1:3306/jog_db?...`(本机 MySQL |
| 5.3 | `spring.datasource.username/password` | `root/root` ⚠️ | 改为业务账号 + 强密码(建议环境变量) | ☐ | 用户 `jog`,密码 `${JOG_DB_PASSWORD}` |
| 5.4 | `spring.data.redis.host/port` | `localhost:6379` | 改为真实 Redis 地址 | ☐ | `127.0.0.1:6379`(本机 Redis |
| 5.5 | `spring.data.redis.password` | 未配置 ⚠️ | 增加 `password` 字段 | ☐ | `password: ${JOG_REDIS_PASSWORD}` |
| 5.6 | `spring.mail.*` | 全部为占位 ⚠️ | 替换为真实 SMTP | ☐ | 使用第三方 SMTP,密码 `${JOG_MAIL_PASSWORD}` |
| 5.7 | `jwt.secret` | 默认演示值 ⚠️ | **必须更换为高强度随机串(≥256bit)** | ☐ | `${JOG_JWT_SECRET}`,使用 `openssl rand -base64 64` 生成 |
| 5.8 | `jwt.access-token-expire` 等 | 7200 / 86400 / 1209600 | 按业务策略复核 | ☐ | 暂保持默认 |
| 5.9 | `springdoc.swagger-ui.enabled` | true | **生产建议关闭**`springdoc.swagger-ui.enabled=false``api-docs.enabled=false` | ☐ | 生产 `false` |
| 5.10 | `logging.level.fun.nojava` | DEBUG | 生产改为 `INFO``WARN` | ☐ | 生产 `INFO` |
| 5.11 | `logging.level.org.springframework.security` | DEBUG | 生产改为 `WARN` | ☐ | 生产 `WARN` |
| 5.12 | `mybatis-plus.configuration.log-impl` | StdOutImpl | 生产建议关闭 SQL 控制台输出 | ☐ | 生产移除该配置 |
| 5.13 | 敏感信息外置 | — | 通过 `JOG_DB_PASSWORD``JOG_REDIS_PASSWORD``JOG_JWT_SECRET` 等环境变量注入 | ☐ | 写入 `/opt/jog/jog.env`(权限 600 |
| 5.14 | 文件上传 / 静态资源目录 | — | 若启用图片上传,提前创建目录并赋权 | ☐ | `/opt/jog/uploads`(属主 `deploy`),系统盘仅 40GB 需关注容量 |
---
## 6. 代码拉取与构建
> 模块依赖:`jog-common` → `jog-framework` → `jog-module-system` → `jog-module-blog` / `jog-module-comment` → `jog-admin`(启动入口)。
| # | 步骤 | 命令 | 状态 | 实际使用 |
|:---:|:---|:---|:---:|:---|
| 6.1 | 拉取代码 | `git clone <repo> && cd Jog` | ☐ | **在本地开发机执行**(服务器不安装 Git 也可) |
| 6.2 | 切换到发布分支 / Tag | `git checkout v1.0.0` | ☐ | 本地切换至发布 Tag |
| 6.3 | 前端依赖安装 | `cd jog-frontend && npm ci` | ☐ | 本地执行 |
| 6.4 | 前端生产构建 | `npm run build`(产物输出到 `jog-admin/src/main/resources/static` | ☐ | 本地执行 |
| 6.5 | 后端打包 | `cd .. && mvn clean package -DskipTests` | ☐ | 本地执行 |
| 6.6 | 验证产物 | `ls jog-admin/target/jog-admin.jar` 存在 | ☐ | 本地验证 jar 存在 |
| 6.7 | 上传 jar(如本地构建) | scp / rsync 至服务器部署目录 `/opt/jog/` | ☐ | `scp jog-admin/target/jog-admin.jar deploy@server:/opt/jog/` |
---
## 7. 应用部署与启动
| # | 项目 | 说明 | 状态 | 实际使用 |
|:---:|:---|:---|:---:|:---|
| 7.1 | 部署目录 | 如 `/opt/jog/`,归属 `deploy:deploy` | ☐ | `/opt/jog/``chown -R deploy:deploy /opt/jog` |
| 7.2 | 日志目录 | 如 `/var/log/jog/`,并赋写权限 | ☐ | `/var/log/jog/`,属主 `deploy` |
| 7.3 | 启动脚本 / Systemd 服务 | 创建 `jog.service`,配置 `Restart=always` | ☐ | 见附录 B`/etc/systemd/system/jog.service` |
| 7.4 | JVM 参数 | `-Xms1g -Xmx1g -XX:+UseG1GC -Dfile.encoding=UTF-8` 等按规格调整 | ☐ | **4GB 内存调小**`-Xms512m -Xmx1024m -XX:+UseG1GC -XX:MaxRAMPercentage=35 -Dfile.encoding=UTF-8` |
| 7.5 | Profile 激活 | `--spring.profiles.active=prod` | ☐ | `--spring.profiles.active=prod` |
| 7.6 | 启动命令示例 | `java $JAVA_OPTS -jar /opt/jog/jog-admin.jar --spring.profiles.active=prod` | ☐ | 同左,由 systemd 拉起 |
| 7.7 | 健康检查 | `curl http://127.0.0.1:8080/`、Swagger 是否按预期关闭 | ☐ | `curl -I http://127.0.0.1:8080/` 返回 200`/swagger-ui.html` 应 404 |
| 7.8 | 开机自启 | `systemctl enable --now jog` | ☐ | `systemctl enable --now jog` |
---
## 8. 反向代理与 HTTPS
| # | 项目 | 说明 | 状态 | 实际使用 |
|:---:|:---|:---|:---:|:---|
| 8.1 | 安装 Nginx | 用于 80/443 入口、反向代理至 8080 | ☐ | `apt install -y nginx`Debian 13 内置) |
| 8.2 | 域名解析 | 将域名 A 记录指向服务器公网 IP | ☐ | 待绑定域名 |
| 8.3 | SSL 证书 | Let's Encryptcertbot)或商业证书 | ☐ | `apt install -y certbot python3-certbot-nginx``certbot --nginx` |
| 8.4 | HTTPS 配置 | 强制 80 → 443 跳转,启用 HSTS | ☐ | certbot 自动配置 + 手工启用 HSTS |
| 8.5 | 反向代理规则 | `location / { proxy_pass http://127.0.0.1:8080; }` 透传 `Host``X-Real-IP``X-Forwarded-For/Proto` | ☐ | `/etc/nginx/sites-available/jog.conf` |
| 8.6 | 上传体积 | `client_max_body_size` 按需调整(富文本图片上传) | ☐ | `client_max_body_size 10m` |
| 8.7 | gzip / brotli | 启用静态资源压缩 | ☐ | 启用 gzip |
| 8.8 | 缓存策略 | 对前端 hash 静态资源设置长缓存 | ☐ | 对 `/assets/` 设置 `expires 30d` |
---
## 9. 防火墙与安全加固
| # | 项目 | 说明 | 状态 | 实际使用 |
|:---:|:---|:---|:---:|:---|
| 9.1 | 安全组 / firewalld / ufw | 仅放行 22 / 80 / 443 | ☐ | Debian 13 使用 `nftables``apt install -y ufw`,仅放行 22/80/443 |
| 9.2 | 关闭对外 8080 | 8080 仅本机访问,由 Nginx 转发 | ☐ | 应用 `server.port=8080` 仅 127.0.0.1,不在防火墙放行 |
| 9.3 | 关闭对外 3306 / 6379 | 数据库与 Redis 仅内网/本机 | ☐ | 均 `bind 127.0.0.1`,不在防火墙放行 |
| 9.4 | SSH 加固 | 改默认端口、密钥登录、禁用 root 登录 | ☐ | 改端口(如 2222)、密钥登录、禁用 root |
| 9.5 | fail2ban | 防 SSH / Nginx 暴力破解 | ☐ | `apt install -y fail2ban`,启用 sshd jail |
| 9.6 | 应用层限流 | 校验 `@RateLimit``RateLimitAspect` 在生产生效 | ☐ | 上线后压测验证 |
| 9.7 | XSS 过滤 | `XssFilter` 已启用,确认未被绕过 | ☐ | 上线后回归测试 |
| 9.8 | JWT 密钥保密 | 不入 Git,仅存服务器环境变量 | ☐ | 写入 `/opt/jog/jog.env`(权限 600 |
| 9.9 | 关闭 Swagger 与 actuator 暴露 | 生产环境严控 | ☐ | `application-prod.yml` 中关闭 |
| 9.10 | 敏感日志脱敏 | 密码、Token 不落日志 | ☐ | 已通过 `logging.level` 控制 |
---
## 10. 监控、日志与备份
| # | 项目 | 说明 | 状态 | 实际使用 |
|:---:|:---|:---|:---:|:---|
| 10.1 | 应用日志路径 | 统一输出至 `/var/log/jog/`,按日滚动 | ☐ | `/var/log/jog/jog.log`logback 按日滚动 |
| 10.2 | 日志保留策略 | 至少保留 14 天,归档压缩 | ☐ | logback 保留 14 天 + gzip |
| 10.3 | 进程监控 | systemd / supervisord 守护,崩溃自动拉起 | ☐ | systemd `Restart=always` |
| 10.4 | 资源监控 | CPU / 内存 / 磁盘 / 网络(如 node_exporter + Prometheus + Grafana | ☐ | **4GB 内存暂不部署 Prometheus 全家桶**,使用 `top/htop``vmstat`、云厂商基础监控 |
| 10.5 | JVM 监控 | 暴露 / 接入监控(actuator + micrometer 视情况开启) | ☐ | 暂不开启(控内存) |
| 10.6 | MySQL 备份 | `mysqldump` 每日定时备份,异地保存 | ☐ | crontab 每日 02:00 `mysqldump jog_db``/opt/backup/`,远端同步 |
| 10.7 | Redis 备份 | RDB/AOF 文件定期备份 | ☐ | 每日打包 `/var/lib/redis/dump.rdb` |
| 10.8 | 文件备份 | 上传文件目录定期备份 | ☐ | 每日同步 `/opt/jog/uploads` 至远端 |
| 10.9 | 异常告警 | 日志 ERROR / 服务宕机告警通道(邮件 / 钉钉 / 企业微信) | ☐ | 接入邮件或企业微信 webhook |
---
## 11. 上线后验证清单
| # | 验证项 | 期望结果 | 状态 | 实际使用 |
|:---:|:---|:---|:---:|:---|
| 11.1 | 访问首页 | `https://your-domain/` 正常加载 Vue 页面 | ☐ | 待绑定域名后验证 |
| 11.2 | 静态资源 | JS/CSS 来自 Nginx,状态码 200 | ☐ | 浏览器 DevTools 验证 |
| 11.3 | 后端接口 | `/api/public/article/list` 返回统一 `ApiResult` | ☐ | `curl` 验证 |
| 11.4 | 注册 / 登录 | 用户可注册、登录、获取 Token | ☐ | 完整业务回归 |
| 11.5 | 管理员登录 | 默认 `admin/Admin@123` 可登录,并已修改密码 | ☐ | 首登后立即改密 |
| 11.6 | Token 刷新 | `/api/public/refresh-token` 正常 | ☐ | Postman 验证 |
| 11.7 | 文章发布 / 评论 | 创建、点赞、评论、嵌套回复均正常 | ☐ | 业务回归 |
| 11.8 | 邮件验证 | 注册邮件可正常收到 | ☐ | 真实邮箱接收测试 |
| 11.9 | Flyway 版本表 | 数据库存在 `flyway_schema_history``success=1` | ☐ | `SELECT * FROM flyway_schema_history` |
| 11.10 | Swagger 关闭 | `/swagger-ui.html` 在生产返回 404 / 403 | ☐ | `curl -I` 验证 |
| 11.11 | 限流验证 | 高频请求触发 429 | ☐ | `ab` / `wrk` 简单压测 |
| 11.12 | XSS 防护 | 提交脚本内容被过滤 | ☐ | 提交 `<script>alert(1)</script>` 验证 |
| 11.13 | HTTPS 与证书 | 浏览器小锁正常,证书未过期 | ☐ | 浏览器 + `openssl s_client` |
| 11.14 | 日志写入 | `/var/log/jog/` 有应用日志输出 | ☐ | `tail -f /var/log/jog/jog.log` |
| 11.15 | 重启恢复 | 重启服务器后服务自启并恢复正常 | ☐ | `reboot` 后验证 |
---
## 附录 A:一键构建参考命令
```bash
# 1. 前端构建(产物自动写入 jog-admin/src/main/resources/static
cd jog-frontend
npm ci
npm run build
# 2. 后端打包
cd ..
mvn clean package -DskipTests
# 3. 上传并运行
scp jog-admin/target/jog-admin.jar deploy@server:/opt/jog/
ssh deploy@server "sudo systemctl restart jog"
```
## 附录 B:systemd 服务模板(参考)
```ini
# /etc/systemd/system/jog.service
[Unit]
Description=Jog System Application
After=network.target mysqld.service redis.service
[Service]
User=deploy
WorkingDirectory=/opt/jog
EnvironmentFile=/opt/jog/jog.env
ExecStart=/usr/bin/java $JAVA_OPTS -jar /opt/jog/jog-admin.jar --spring.profiles.active=prod
SuccessExitStatus=143
Restart=always
RestartSec=5
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
```
```bash
# /opt/jog/jog.env (权限 600,仅 deploy 可读)
# 4GB 内存机器:堆内存调低,给 MySQL/Redis/系统留出空间
JAVA_OPTS=-Xms512m -Xmx1024m -XX:+UseG1GC -XX:MaxRAMPercentage=35 -Dfile.encoding=UTF-8
JOG_DB_PASSWORD=********
JOG_REDIS_PASSWORD=********
JOG_JWT_SECRET=********
JOG_MAIL_PASSWORD=********
```
---
> 本清单基于当前代码库(`pom.xml` Java 21、`application.yml`、`vite.config.js` 一体化构建配置)以及目标服务器(Debian 13.2 / 4C4G / 40GB)生成,后续若引入对象存储、CDN、消息队列、ES 检索等组件,请同步在本文件追加章节并维护。
>
> ⚠️ **4GB 内存预算参考**JVM ≤ 1GB(堆 512m1024m)、MySQL ≤ 1GB、Redis ≤ 256MB、Nginx + 系统 ≈ 512MB,剩余 ~1GB 余量;如果出现 OOM,优先降低 MySQL `innodb_buffer_pool_size` 或将 SMTP/构建迁出本机。