chore(release): initialize separated production env
This commit is contained in:
Executable
+83
@@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
STAGING_ENV=${STAGING_ENV:-/var/lib/xiaoxia-saas-staging/.env}
|
||||
PRODUCTION_DIR=${PRODUCTION_DIR:-/var/lib/xiaoxia-saas-production}
|
||||
PRODUCTION_ENV=${PRODUCTION_ENV:-$PRODUCTION_DIR/.env}
|
||||
GENERATED_DIR=${GENERATED_DIR:-$PRODUCTION_DIR/generated}
|
||||
FORCE=${FORCE:-false}
|
||||
|
||||
if [ -e "$PRODUCTION_ENV" ] && [ "$FORCE" != "true" ]; then
|
||||
echo "ERROR: production env already exists: $PRODUCTION_ENV" >&2
|
||||
echo "Set FORCE=true only after manually reviewing the existing file." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$PRODUCTION_DIR" "$GENERATED_DIR"
|
||||
chmod 700 "$PRODUCTION_DIR"
|
||||
|
||||
get_staging_value() {
|
||||
key="$1"
|
||||
if [ -f "$STAGING_ENV" ]; then
|
||||
grep -E "^${key}=" "$STAGING_ENV" | tail -1 | cut -d= -f2- || true
|
||||
fi
|
||||
}
|
||||
|
||||
random_secret() {
|
||||
python3 - <<'PY'
|
||||
import secrets
|
||||
print(secrets.token_urlsafe(48))
|
||||
PY
|
||||
}
|
||||
|
||||
OSS_ENDPOINT=${OSS_ENDPOINT:-$(get_staging_value OSS_ENDPOINT)}
|
||||
OSS_BUCKET_NAME=${OSS_BUCKET_NAME:-$(get_staging_value OSS_BUCKET_NAME)}
|
||||
OSS_ACCESS_KEY_ID=${OSS_ACCESS_KEY_ID:-$(get_staging_value OSS_ACCESS_KEY_ID)}
|
||||
OSS_ACCESS_KEY_SECRET=${OSS_ACCESS_KEY_SECRET:-$(get_staging_value OSS_ACCESS_KEY_SECRET)}
|
||||
JWT_SECRET_KEY=${JWT_SECRET_KEY:-$(random_secret)}
|
||||
|
||||
cat > "$PRODUCTION_ENV" <<EOF
|
||||
APP_NAME=xiaoxia-saas
|
||||
APP_VERSION=0.1.0
|
||||
APP_ENV=production
|
||||
ENVIRONMENT=production
|
||||
DEBUG=false
|
||||
AUTO_CREATE_SCHEMA=false
|
||||
USE_IN_MEMORY_DB=false
|
||||
|
||||
ENV=production
|
||||
API_PORT=8001
|
||||
WEB_PORT=3000
|
||||
PUBLIC_API_BASE_URL=https://api.xiaoxiajianji.com
|
||||
GENERATED_FILES_HOST_DIR=$GENERATED_DIR
|
||||
|
||||
DATABASE_URL=postgresql+psycopg://xiaoxia:CHANGE_ME_PRODUCTION_DB_PASSWORD@xiaoxia-postgres-production:5432/xiaoxia_saas
|
||||
REDIS_URL=redis://xiaoxia-redis-production:6379/0
|
||||
CELERY_BROKER_URL=redis://xiaoxia-redis-production:6379/0
|
||||
CELERY_RESULT_BACKEND=redis://xiaoxia-redis-production:6379/1
|
||||
ENABLE_REDIS_SESSIONS=true
|
||||
|
||||
JWT_SECRET_KEY=$JWT_SECRET_KEY
|
||||
|
||||
ENABLE_EMAIL_DELIVERY=false
|
||||
SMTP_HOST=
|
||||
SMTP_PORT=587
|
||||
SMTP_USER=
|
||||
SMTP_PASSWORD=
|
||||
SMTP_FROM_EMAIL=
|
||||
SMTP_FROM_NAME=小虾 SaaS
|
||||
SMTP_USE_TLS=true
|
||||
|
||||
OSS_ENDPOINT=$OSS_ENDPOINT
|
||||
OSS_ACCESS_KEY_ID=$OSS_ACCESS_KEY_ID
|
||||
OSS_ACCESS_KEY_SECRET=$OSS_ACCESS_KEY_SECRET
|
||||
OSS_BUCKET_NAME=$OSS_BUCKET_NAME
|
||||
|
||||
LOG_LEVEL=INFO
|
||||
CORS_ORIGINS_RAW=https://xiaoxiajianji.com,https://api.xiaoxiajianji.com
|
||||
EOF
|
||||
|
||||
chmod 600 "$PRODUCTION_ENV"
|
||||
|
||||
echo "OK production env initialized: $PRODUCTION_ENV"
|
||||
echo "NEXT: replace CHANGE_ME_PRODUCTION_DB_PASSWORD and provision xiaoxia-postgres-production/xiaoxia-redis-production before deployment."
|
||||
@@ -83,7 +83,7 @@ def validate(values: dict[str, str], strict_external: bool) -> list[str]:
|
||||
errors.append("DEBUG must be false in production")
|
||||
|
||||
external_requirements = []
|
||||
if strict_external or is_enabled(values.get("ENABLE_EMAIL_DELIVERY")):
|
||||
if is_enabled(values.get("ENABLE_EMAIL_DELIVERY")):
|
||||
external_requirements.extend(REQUIRED_SMTP)
|
||||
if strict_external:
|
||||
external_requirements.extend(REQUIRED_OSS)
|
||||
@@ -117,7 +117,7 @@ def main() -> int:
|
||||
parser.add_argument(
|
||||
"--strict-external",
|
||||
action="store_true",
|
||||
help="Require SMTP, Redis sessions, and OSS credentials for production readiness.",
|
||||
help="Require Redis sessions and OSS credentials for production readiness. SMTP is required only when ENABLE_EMAIL_DELIVERY=true.",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user