feat: 新增deploy.sh --init-env一键初始化.env+完善JWT_SECRET管理文档
新增 --init-env 功能: - 自动生成 256 位随机 JWT_SECRET (openssl rand -base64 32) - 推送完整.env模板到服务器,设置权限600 - 文件已存在时先备份再覆盖,有确认提示 - dry-run 模式下安全预览 JWT_SECRET 管理方案: - dev/prod 使用不同密钥 - 仅在服务器.env中存储(不进入Git/TOML) - deploy.sh check_env_file() 部署前自动验证 - AGENTS.md 新增完整管理文档(生成/存储/验证/轮换) deploy.sh 帮助文档同步更新 --init-env 说明
This commit is contained in:
47
AGENTS.md
47
AGENTS.md
@@ -581,6 +581,7 @@ let new_expires = base_time + days(pkg_days);
|
||||
| `--skip-tests` | 跳过部署后测试 |
|
||||
| `--rollback` | 回滚到上一个备份版本 |
|
||||
| `--backup-list` | 列出可用备份 |
|
||||
| `--init-env` | 初始化远程 .env(生成随机 JWT_SECRET + 推送模板到服务器) |
|
||||
| `--help, -h` | 显示帮助信息 |
|
||||
|
||||
**示例:**
|
||||
@@ -588,6 +589,7 @@ let new_expires = base_time + days(pkg_days);
|
||||
./deploy.sh production --dry-run # 预览生产部署
|
||||
./deploy.sh production --yes # 无需确认直接部署
|
||||
./deploy.sh development --skip-tests # 跳过测试
|
||||
./deploy.sh production --init-env # 初始化生产 .env
|
||||
./deploy.sh production --rollback # 回滚到上一个版本
|
||||
./deploy.sh production --backup-list # 列出可用备份
|
||||
```
|
||||
@@ -660,12 +662,49 @@ WEBHOOK_URL="https://example.com/webhook" ./deploy.sh production
|
||||
|
||||
参考本地文件:`rust-backend.service`(生产)、`rust-backend-dev.service`(开发)
|
||||
|
||||
**2. 创建 .env 环境配置:**
|
||||
**2. 初始化 .env 环境配置(推荐使用 deploy.sh):**
|
||||
|
||||
开发环境:`/root/rust/rust_backend_dev/.env`
|
||||
生产环境:`/root/rust/rust_backend/.env`
|
||||
```bash
|
||||
# 生产环境 — 自动生成随机 JWT_SECRET,推送 .env 模板到服务器
|
||||
./deploy.sh production --init-env
|
||||
|
||||
参考 `.env.example` 或询问运维获取。
|
||||
# 开发环境
|
||||
./deploy.sh development --init-env
|
||||
```
|
||||
|
||||
`--init-env` 会:
|
||||
- 生成 256 位随机 `JWT_SECRET`(`openssl rand -base64 32`)
|
||||
- 推送 `.env` 文件到服务器 `${REMOTE_DIR}/.env`
|
||||
- 设置文件权限 `600`(仅 root 可读)
|
||||
- 如文件已存在,先备份再覆盖
|
||||
|
||||
执行后仍需 SSH 到服务器填写以下手动变量:
|
||||
|
||||
```bash
|
||||
ssh root@1panel-server
|
||||
vim /root/rust/rust_backend/.env
|
||||
|
||||
# 必须手动填写:
|
||||
DATABASE_URL=postgres://user:pass@host:5432/dbname
|
||||
WECHAT_APPID=wx...
|
||||
WECHAT_SECRET=xxx
|
||||
```
|
||||
|
||||
> **不建议**手动创建 `.env`——因为 `deploy.sh --init-env` 会自动生成强随机 `JWT_SECRET`,手动创建容易忘记生成或使用弱密钥。
|
||||
|
||||
### JWT_SECRET 管理
|
||||
|
||||
| 生命周期 | 操作 | 说明 |
|
||||
|----------|------|------|
|
||||
| **生成** | `openssl rand -base64 32` | 首次 `deploy.sh --init-env` 自动完成 |
|
||||
| **存储** | 服务器 `.env`,权限 600 | 不进入 Git,不进入 TOML 配置 |
|
||||
| **验证** | `deploy.sh check_env_file` | 部署前自动检查是否缺失 |
|
||||
| **轮换** | 手动替换 → 重启服务 | 旧 token 失效,所有用户需重新登录 |
|
||||
|
||||
**原则:**
|
||||
- Dev 和 Prod 使用**不同**的 JWT_SECRET
|
||||
- JWT_SECRET **永不出现在** `config/*.toml` 或任何 Git 管理的文件中
|
||||
- 服务器 `.env` 文件**不通过 `deploy.sh` 同步**(不会上传到服务器),仅手动或通过 `--init-env` 创建
|
||||
|
||||
**3. 启用服务:**
|
||||
|
||||
|
||||
111
deploy.sh
111
deploy.sh
@@ -31,6 +31,7 @@ TAIL_LOGS=false
|
||||
LOG_LINES=50
|
||||
VIEW_STATUS=false
|
||||
POST_DEPLOY_LOGS=false
|
||||
INIT_ENV=false
|
||||
|
||||
# 全局变量(部署流程中使用)
|
||||
BACKUP_PATH=""
|
||||
@@ -73,6 +74,9 @@ while [[ $# -gt 0 ]]; do
|
||||
--post-logs)
|
||||
POST_DEPLOY_LOGS=true
|
||||
;;
|
||||
--init-env)
|
||||
INIT_ENV=true
|
||||
;;
|
||||
--help|-h)
|
||||
echo "用法: $0 [development|production] [options]"
|
||||
echo ""
|
||||
@@ -86,6 +90,7 @@ while [[ $# -gt 0 ]]; do
|
||||
echo " --tail [N] 实时跟踪后端日志(Ctrl+C 退出)"
|
||||
echo " --status 查看服务状态"
|
||||
echo " --post-logs 部署后自动显示日志"
|
||||
echo " --init-env 初始化远程 .env 文件(生成随机 JWT_SECRET,推送模板到服务器)"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
@@ -571,6 +576,106 @@ check_env_file() {
|
||||
log_info ".env 文件检查通过(${#required_vars[@]} 个必需变量均已配置)"
|
||||
fi
|
||||
}
|
||||
|
||||
# 初始化远程 .env 文件(生成随机 JWT_SECRET,推送模板到服务器)
|
||||
init_env() {
|
||||
log_step "初始化远程 .env 文件..."
|
||||
|
||||
if [ "$DRY_RUN" = true ]; then
|
||||
log_dry "在 ${REMOTE_HOST}:${REMOTE_DIR}/.env 生成带随机 JWT_SECRET 的配置文件"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# 1. 检查服务器 .env 是否已存在
|
||||
local env_exists=false
|
||||
if ssh "${REMOTE_USER}@${REMOTE_HOST}" "test -f '${REMOTE_DIR}/.env'" 2>/dev/null; then
|
||||
env_exists=true
|
||||
log_warn ".env 文件已存在: ${REMOTE_DIR}/.env"
|
||||
echo ""
|
||||
echo -e " ${YELLOW}文件已存在,继续将覆盖现有配置!${NC}"
|
||||
echo ""
|
||||
read -p "是否覆盖? [y/N] " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
log_warn "已取消"
|
||||
return 0
|
||||
fi
|
||||
# 备份旧文件
|
||||
local backup_file=".env.backup.$(date +%Y%m%d_%H%M%S)"
|
||||
ssh "${REMOTE_USER}@${REMOTE_HOST}" "cp '${REMOTE_DIR}/.env' '${REMOTE_DIR}/${backup_file}'" 2>/dev/null || true
|
||||
log_info "旧文件已备份: ${backup_file}"
|
||||
fi
|
||||
|
||||
# 2. 生成随机 JWT_SECRET
|
||||
local jwt_secret
|
||||
if command -v openssl &>/dev/null; then
|
||||
jwt_secret=$(openssl rand -base64 32 | tr -d '\n')
|
||||
else
|
||||
jwt_secret="change-me-$(date +%s)-$$"
|
||||
log_warn "openssl 未找到,使用临时密钥(请手动替换)"
|
||||
fi
|
||||
|
||||
# 3. 构建 .env 内容
|
||||
local env_content
|
||||
env_content=$(cat <<ENV_EOF
|
||||
# ASD Rust Backend - ${APP_ENV} 环境配置
|
||||
# 由 deploy.sh --init-env 自动生成于 $(date '+%Y-%m-%d %H:%M:%S')
|
||||
|
||||
APP_ENV=${APP_ENV}
|
||||
|
||||
# 数据库配置
|
||||
DATABASE_URL=请替换为实际数据库连接字符串
|
||||
|
||||
# 微信认证
|
||||
WECHAT_APPID=请替换为实际微信 AppID
|
||||
WECHAT_SECRET=请替换为实际微信 Secret
|
||||
|
||||
# JWT 配置(自动生成)
|
||||
JWT_SECRET=${jwt_secret}
|
||||
|
||||
# SSL 配置(生产环境必须)
|
||||
SSL_KEY_PATH=/etc/ssl/private/private.key
|
||||
SSL_CERT_PATH=/etc/ssl/certs/full_chain.pem
|
||||
|
||||
# 日志级别
|
||||
RUST_LOG=info
|
||||
|
||||
# 应用版本
|
||||
APP_VERSION=0.3.0
|
||||
|
||||
# 免费用户数据限制
|
||||
FREE_USER_DATA_LIMIT=20
|
||||
|
||||
# ===== 支付宝支付配置(可选,不配置则使用模拟支付) =====
|
||||
# ALIPAY_APP_ID=your_alipay_app_id
|
||||
# ALIPAY_PRIVATE_KEY=your_private_key_content
|
||||
# ALIPAY_ALIPAY_PUBLIC_KEY=alipay_public_key_content
|
||||
# ALIPAY_GATEWAY=https://openapi-sandbox.dl.alipaydev.com/gateway.do
|
||||
ENV_EOF
|
||||
)
|
||||
|
||||
# 4. 推送 .env 到服务器
|
||||
echo "$env_content" | ssh "${REMOTE_USER}@${REMOTE_HOST}" "cat > '${REMOTE_DIR}/.env'"
|
||||
ssh "${REMOTE_USER}@${REMOTE_HOST}" "chmod 600 '${REMOTE_DIR}/.env'"
|
||||
|
||||
log_info ".env 文件已生成: ${REMOTE_DIR}/.env"
|
||||
log_warn "请 SSH 到服务器手动填写以下变量:"
|
||||
echo ""
|
||||
echo -e " ${YELLOW}DATABASE_URL${NC} — 数据库连接字符串"
|
||||
echo -e " ${YELLOW}WECHAT_APPID${NC} — 微信小程序 AppID"
|
||||
echo -e " ${YELLOW}WECHAT_SECRET${NC} — 微信小程序 Secret"
|
||||
echo ""
|
||||
log_info "JWT_SECRET 已自动生成(无需修改)"
|
||||
log_info "文件权限已设为 600(仅所有者可读)"
|
||||
echo ""
|
||||
|
||||
# 5. 确认是否需要重启服务
|
||||
if [ "$env_exists" = true ]; then
|
||||
log_info "如果已部署的服务正在运行,建议重启:"
|
||||
echo -e " ${GREEN}ssh ${REMOTE_USER}@${REMOTE_HOST} 'systemctl restart ${SERVICE_NAME}'${NC}"
|
||||
fi
|
||||
}
|
||||
|
||||
check_dependencies() {
|
||||
log_step "检查依赖..."
|
||||
local deps=("cargo" "rsync" "ssh")
|
||||
@@ -1376,6 +1481,12 @@ main() {
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$INIT_ENV" = true ]; then
|
||||
ssh_connect
|
||||
init_env
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$VIEW_LOGS" = true ]; then
|
||||
ssh_connect
|
||||
view_logs
|
||||
|
||||
Reference in New Issue
Block a user