feat(deploy): provision store monitoring secrets
这个提交包含在:
父节点
475067562c
当前提交
7912b6a527
@ -60,6 +60,15 @@ XUQM_JWT_SECRET=
|
|||||||
# 留空时 install.sh 自动生成
|
# 留空时 install.sh 自动生成
|
||||||
SDK_INTERNAL_TOKEN=
|
SDK_INTERNAL_TOKEN=
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# 应用商店监测 Secrets 主密钥
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# 32 字节随机值的 Base64。用于 AES-256-GCM 加密商店监测凭据和 Webhook 密钥。
|
||||||
|
# 首次安装自动生成;丢失后无法解密已有凭据,禁止跨公有化/私有化部署复用。
|
||||||
|
XUQM_STORE_SECRET_MASTER_KEY=
|
||||||
|
XUQM_STORE_SECRET_KEY_VERSION=v1
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# SMTP 邮件密码(发送验证码邮件)
|
# SMTP 邮件密码(发送验证码邮件)
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|||||||
@ -152,6 +152,7 @@ services:
|
|||||||
env_file:
|
env_file:
|
||||||
- ./config/xuqm.env
|
- ./config/xuqm.env
|
||||||
- ./config/secrets.env
|
- ./config/secrets.env
|
||||||
|
- ./config/mail/smtp.env
|
||||||
- ./config/vendors/store-submit.env # 各应用市场发布凭据
|
- ./config/vendors/store-submit.env # 各应用市场发布凭据
|
||||||
environment:
|
environment:
|
||||||
SPRING_DATASOURCE_URL: "jdbc:mysql://${MYSQL_HOST}:${MYSQL_PORT:-3306}/${MYSQL_DATABASE:-xuqm_private}?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true"
|
SPRING_DATASOURCE_URL: "jdbc:mysql://${MYSQL_HOST}:${MYSQL_PORT:-3306}/${MYSQL_DATABASE:-xuqm_private}?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true"
|
||||||
|
|||||||
@ -29,6 +29,8 @@
|
|||||||
| `REDIS_PASSWORD` | Redis 密码 |
|
| `REDIS_PASSWORD` | Redis 密码 |
|
||||||
| `SPRING_DATASOURCE_PASSWORD` | Spring 读取的数据库密码(与 `MYSQL_PASSWORD` 值相同) |
|
| `SPRING_DATASOURCE_PASSWORD` | Spring 读取的数据库密码(与 `MYSQL_PASSWORD` 值相同) |
|
||||||
| `SPRING_DATA_REDIS_PASSWORD` | Spring 读取的 Redis 密码(与 `REDIS_PASSWORD` 值相同) |
|
| `SPRING_DATA_REDIS_PASSWORD` | Spring 读取的 Redis 密码(与 `REDIS_PASSWORD` 值相同) |
|
||||||
|
| `XUQM_STORE_SECRET_MASTER_KEY` | 商店监测凭据 AES-256-GCM 主密钥(32 字节 Base64) |
|
||||||
|
| `XUQM_STORE_SECRET_KEY_VERSION` | 主密钥版本标识,默认 `v1` |
|
||||||
|
|
||||||
> **设计说明**:Spring 通过 `env_file` 直接读取 `SPRING_DATASOURCE_PASSWORD`,而非通过 `docker-compose.yml` 的 `environment:` 节替换 `${MYSQL_PASSWORD}`。这是因为 compose 变量替换在 shell 中找不到该变量时会替换为空字符串,导致"Access denied (using password: NO)"。旧版部署如缺少这两个字段,`reset.sh` 和 `update.sh` 会自动补齐。
|
> **设计说明**:Spring 通过 `env_file` 直接读取 `SPRING_DATASOURCE_PASSWORD`,而非通过 `docker-compose.yml` 的 `environment:` 节替换 `${MYSQL_PASSWORD}`。这是因为 compose 变量替换在 shell 中找不到该变量时会替换为空字符串,导致"Access denied (using password: NO)"。旧版部署如缺少这两个字段,`reset.sh` 和 `update.sh` 会自动补齐。
|
||||||
|
|
||||||
@ -133,7 +135,9 @@ Web 代理会覆盖上游缓存头:入口 HTML、manifest 和普通路由使
|
|||||||
|
|
||||||
## `config/mail/smtp.env`
|
## `config/mail/smtp.env`
|
||||||
|
|
||||||
邮件服务配置,不填则邮件功能不可用,不影响其他服务启动。
|
邮件服务配置,不填则邮件功能不可用,不影响其他服务启动。`tenant-service`
|
||||||
|
用于账号邮件,`update-service` 用于租户显式启用的商店状态邮件通知;通知默认关闭,
|
||||||
|
邮件发送失败不得影响商店状态同步和平台主流程。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@ -157,6 +157,17 @@ set_env_value "$ROOT_DIR/config/secrets.env" "MYSQL_PASSWORD" "$MYSQL_PASSWORD"
|
|||||||
[ -n "${MYSQL_ROOT_PASSWORD:-}" ] && \
|
[ -n "${MYSQL_ROOT_PASSWORD:-}" ] && \
|
||||||
set_env_value "$ROOT_DIR/config/secrets.env" "MYSQL_ROOT_PASSWORD" "$MYSQL_ROOT_PASSWORD"
|
set_env_value "$ROOT_DIR/config/secrets.env" "MYSQL_ROOT_PASSWORD" "$MYSQL_ROOT_PASSWORD"
|
||||||
set_env_value "$ROOT_DIR/config/secrets.env" "REDIS_PASSWORD" "$REDIS_PASSWORD"
|
set_env_value "$ROOT_DIR/config/secrets.env" "REDIS_PASSWORD" "$REDIS_PASSWORD"
|
||||||
|
set_env_value "$ROOT_DIR/config/secrets.env" "SPRING_DATASOURCE_PASSWORD" "$MYSQL_PASSWORD"
|
||||||
|
set_env_value "$ROOT_DIR/config/secrets.env" "SPRING_DATA_REDIS_PASSWORD" "$REDIS_PASSWORD"
|
||||||
|
ensure_env_value "$ROOT_DIR/config/secrets.env" "XUQM_JWT_SECRET" \
|
||||||
|
"${XUQM_JWT_SECRET:-}" "$(random_secret)$(random_secret)" >/dev/null
|
||||||
|
ensure_env_value "$ROOT_DIR/config/secrets.env" "SDK_INTERNAL_TOKEN" \
|
||||||
|
"${SDK_INTERNAL_TOKEN:-}" "$(random_secret)" >/dev/null
|
||||||
|
ensure_env_value "$ROOT_DIR/config/secrets.env" "XUQM_STORE_SECRET_MASTER_KEY" \
|
||||||
|
"${XUQM_STORE_SECRET_MASTER_KEY:-}" "$(random_aes256_base64)" >/dev/null
|
||||||
|
set_env_value "$ROOT_DIR/config/secrets.env" "XUQM_STORE_SECRET_KEY_VERSION" \
|
||||||
|
"${XUQM_STORE_SECRET_KEY_VERSION:-v1}"
|
||||||
|
chmod 600 "$ROOT_DIR/config/secrets.env"
|
||||||
|
|
||||||
"$ROOT_DIR/scripts/render-config.sh"
|
"$ROOT_DIR/scripts/render-config.sh"
|
||||||
|
|
||||||
|
|||||||
@ -380,6 +380,15 @@ EOF
|
|||||||
ok ".env 已写入"
|
ok ".env 已写入"
|
||||||
|
|
||||||
# config/secrets.env — 敏感信息(权限 600)
|
# config/secrets.env — 敏感信息(权限 600)
|
||||||
|
if command -v openssl >/dev/null 2>&1; then
|
||||||
|
XUQM_JWT_SECRET="$(openssl rand -base64 48 | tr -d '\n')"
|
||||||
|
SDK_INTERNAL_TOKEN="$(openssl rand -base64 32 | tr -d '\n')"
|
||||||
|
XUQM_STORE_SECRET_MASTER_KEY="$(openssl rand -base64 32 | tr -d '\n')"
|
||||||
|
else
|
||||||
|
XUQM_JWT_SECRET="$(dd if=/dev/urandom bs=48 count=1 2>/dev/null | base64 | tr -d '\n')"
|
||||||
|
SDK_INTERNAL_TOKEN="$(dd if=/dev/urandom bs=32 count=1 2>/dev/null | base64 | tr -d '\n')"
|
||||||
|
XUQM_STORE_SECRET_MASTER_KEY="$(dd if=/dev/urandom bs=32 count=1 2>/dev/null | base64 | tr -d '\n')"
|
||||||
|
fi
|
||||||
mkdir -p "$ROOT_DIR/config"
|
mkdir -p "$ROOT_DIR/config"
|
||||||
cat > "$ROOT_DIR/config/secrets.env" <<EOF
|
cat > "$ROOT_DIR/config/secrets.env" <<EOF
|
||||||
# XuqmGroup 私有化部署 — 敏感凭据(请妥善保管,chmod 600)
|
# XuqmGroup 私有化部署 — 敏感凭据(请妥善保管,chmod 600)
|
||||||
@ -389,6 +398,10 @@ REDIS_PASSWORD=${REDIS_PASSWORD}
|
|||||||
# Spring 直接读取的 env 名(避免 docker compose 变量替换时因 shell 缺失变量而变成空字符串)
|
# Spring 直接读取的 env 名(避免 docker compose 变量替换时因 shell 缺失变量而变成空字符串)
|
||||||
SPRING_DATASOURCE_PASSWORD=${MYSQL_PASSWORD}
|
SPRING_DATASOURCE_PASSWORD=${MYSQL_PASSWORD}
|
||||||
SPRING_DATA_REDIS_PASSWORD=${REDIS_PASSWORD}
|
SPRING_DATA_REDIS_PASSWORD=${REDIS_PASSWORD}
|
||||||
|
XUQM_JWT_SECRET=${XUQM_JWT_SECRET}
|
||||||
|
SDK_INTERNAL_TOKEN=${SDK_INTERNAL_TOKEN}
|
||||||
|
XUQM_STORE_SECRET_MASTER_KEY=${XUQM_STORE_SECRET_MASTER_KEY}
|
||||||
|
XUQM_STORE_SECRET_KEY_VERSION=v1
|
||||||
EOF
|
EOF
|
||||||
chmod 600 "$ROOT_DIR/config/secrets.env"
|
chmod 600 "$ROOT_DIR/config/secrets.env"
|
||||||
ok "config/secrets.env 已写入 (chmod 600)"
|
ok "config/secrets.env 已写入 (chmod 600)"
|
||||||
|
|||||||
@ -60,6 +60,14 @@ random_secret() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
random_aes256_base64() {
|
||||||
|
if command -v openssl >/dev/null 2>&1; then
|
||||||
|
openssl rand -base64 32 | tr -d '\n'
|
||||||
|
else
|
||||||
|
dd if=/dev/urandom bs=32 count=1 2>/dev/null | base64 | tr -d '\n'
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
ensure_secret_file() {
|
ensure_secret_file() {
|
||||||
if [ ! -f "$ROOT_DIR/config/secrets.env" ]; then
|
if [ ! -f "$ROOT_DIR/config/secrets.env" ]; then
|
||||||
cp "$ROOT_DIR/config/secrets.env.example" "$ROOT_DIR/config/secrets.env"
|
cp "$ROOT_DIR/config/secrets.env.example" "$ROOT_DIR/config/secrets.env"
|
||||||
|
|||||||
@ -90,6 +90,18 @@ if ! grep -q "^SPRING_DATA_REDIS_PASSWORD=" "$ROOT_DIR/config/secrets.env" 2>/de
|
|||||||
fi
|
fi
|
||||||
[ "$_patched" -eq 1 ] && ok "secrets.env 已补齐 SPRING_DATASOURCE_PASSWORD / SPRING_DATA_REDIS_PASSWORD"
|
[ "$_patched" -eq 1 ] && ok "secrets.env 已补齐 SPRING_DATASOURCE_PASSWORD / SPRING_DATA_REDIS_PASSWORD"
|
||||||
|
|
||||||
|
if ! grep -q "^XUQM_STORE_SECRET_MASTER_KEY=." "$ROOT_DIR/config/secrets.env" 2>/dev/null; then
|
||||||
|
if command -v openssl >/dev/null 2>&1; then
|
||||||
|
_store_master_key="$(openssl rand -base64 32 | tr -d '\n')"
|
||||||
|
else
|
||||||
|
_store_master_key="$(dd if=/dev/urandom bs=32 count=1 2>/dev/null | base64 | tr -d '\n')"
|
||||||
|
fi
|
||||||
|
printf 'XUQM_STORE_SECRET_MASTER_KEY=%s\n' "$_store_master_key" >> "$ROOT_DIR/config/secrets.env"
|
||||||
|
printf 'XUQM_STORE_SECRET_KEY_VERSION=v1\n' >> "$ROOT_DIR/config/secrets.env"
|
||||||
|
chmod 600 "$ROOT_DIR/config/secrets.env"
|
||||||
|
ok "secrets.env 已生成应用商店监测加密主密钥"
|
||||||
|
fi
|
||||||
|
|
||||||
_CONSOLE_DOMAIN="$(grep '^CONSOLE_DOMAIN=' "$ROOT_DIR/config/xuqm.env" 2>/dev/null \
|
_CONSOLE_DOMAIN="$(grep '^CONSOLE_DOMAIN=' "$ROOT_DIR/config/xuqm.env" 2>/dev/null \
|
||||||
| cut -d= -f2- | tr -d '"' | tr -d "'")"
|
| cut -d= -f2- | tr -d '"' | tr -d "'")"
|
||||||
ok "CONSOLE_DOMAIN=${_CONSOLE_DOMAIN:-(未设置)}"
|
ok "CONSOLE_DOMAIN=${_CONSOLE_DOMAIN:-(未设置)}"
|
||||||
|
|||||||
@ -123,6 +123,20 @@ if ! grep -q "^SPRING_DATA_REDIS_PASSWORD=" "$ROOT_DIR/config/secrets.env" 2>/de
|
|||||||
fi
|
fi
|
||||||
[ "$_patched" -eq 1 ] && ok "secrets.env 已补齐 SPRING_DATASOURCE_PASSWORD / SPRING_DATA_REDIS_PASSWORD"
|
[ "$_patched" -eq 1 ] && ok "secrets.env 已补齐 SPRING_DATASOURCE_PASSWORD / SPRING_DATA_REDIS_PASSWORD"
|
||||||
|
|
||||||
|
# 商店监测凭据使用独立的 AES-256-GCM 主密钥。升级旧部署时只生成一次,
|
||||||
|
# 后续更新必须保留原值,否则已有商店凭据将无法解密。
|
||||||
|
if ! grep -q "^XUQM_STORE_SECRET_MASTER_KEY=." "$ROOT_DIR/config/secrets.env" 2>/dev/null; then
|
||||||
|
if command -v openssl >/dev/null 2>&1; then
|
||||||
|
_store_master_key="$(openssl rand -base64 32 | tr -d '\n')"
|
||||||
|
else
|
||||||
|
_store_master_key="$(dd if=/dev/urandom bs=32 count=1 2>/dev/null | base64 | tr -d '\n')"
|
||||||
|
fi
|
||||||
|
printf 'XUQM_STORE_SECRET_MASTER_KEY=%s\n' "$_store_master_key" >> "$ROOT_DIR/config/secrets.env"
|
||||||
|
printf 'XUQM_STORE_SECRET_KEY_VERSION=v1\n' >> "$ROOT_DIR/config/secrets.env"
|
||||||
|
chmod 600 "$ROOT_DIR/config/secrets.env"
|
||||||
|
ok "secrets.env 已生成应用商店监测加密主密钥"
|
||||||
|
fi
|
||||||
|
|
||||||
# 迁移:补齐 PRIVATE_DEPLOY_ROOT(一键更新功能需要此变量,旧版部署升级时自动写入)
|
# 迁移:补齐 PRIVATE_DEPLOY_ROOT(一键更新功能需要此变量,旧版部署升级时自动写入)
|
||||||
if ! grep -q "^PRIVATE_DEPLOY_ROOT=" "$ROOT_DIR/.env" 2>/dev/null; then
|
if ! grep -q "^PRIVATE_DEPLOY_ROOT=" "$ROOT_DIR/.env" 2>/dev/null; then
|
||||||
printf '\nPRIVATE_DEPLOY_ROOT=%s\n' "$ROOT_DIR" >> "$ROOT_DIR/.env"
|
printf '\nPRIVATE_DEPLOY_ROOT=%s\n' "$ROOT_DIR" >> "$ROOT_DIR/.env"
|
||||||
|
|||||||
正在加载...
在新工单中引用
屏蔽一个用户