Files
QSfera/Server/devtools/deployments/qsfera_full/validate-production-env.sh
T
Курнат Андрей 43caef7a6a Prepare QSfera production release
2026-06-08 19:57:40 +03:00

156 lines
3.7 KiB
Bash

#!/usr/bin/env sh
set -eu
ENV_FILE="${1:-.env}"
errors=0
warnings=0
if [ ! -f "$ENV_FILE" ]; then
echo "ERROR: env file not found: $ENV_FILE" >&2
exit 1
fi
value() {
key="$1"
awk -v key="$key" '
/^[[:space:]]*#/ || /^[[:space:]]*$/ { next }
{
line = $0
sub(/\r$/, "", line)
split(line, parts, "=")
current = parts[1]
gsub(/^[ \t]+|[ \t]+$/, "", current)
if (current == key) {
sub(/^[^=]*=/, "", line)
gsub(/^"/, "", line)
gsub(/"$/, "", line)
gsub(/^'\''/, "", line)
gsub(/'\''$/, "", line)
print line
exit
}
}
' "$ENV_FILE"
}
is_placeholder() {
case "${1:-}" in
""|"<"*">"|*example.com*|"change-me"|"changeme"|"password"|"secret")
return 0
;;
*)
return 1
;;
esac
}
error() {
errors=$((errors + 1))
echo "ERROR: $1" >&2
}
warn() {
warnings=$((warnings + 1))
echo "WARN: $1" >&2
}
require_value() {
key="$1"
label="${2:-$1}"
current="$(value "$key")"
if is_placeholder "$current"; then
error "$label must be set to a production value."
fi
}
require_secret() {
key="$1"
current="$(value "$key")"
if is_placeholder "$current"; then
error "$key must be set."
return
fi
case "$current" in
admin|demo|keycloak|qsfera|qsfera-secret-key)
error "$key uses a known demo/default value."
return
;;
esac
if [ "${#current}" -lt 16 ]; then
error "$key must be at least 16 characters."
fi
}
enabled() {
current="$(value "$1")"
[ -n "$current" ]
}
require_value OC_DOMAIN "OC_DOMAIN"
require_value TRAEFIK_ACME_MAIL "TRAEFIK_ACME_MAIL"
require_secret ADMIN_PASSWORD
case "$(value INSECURE)" in
true|TRUE|1|yes|YES)
error "INSECURE must be false for production."
;;
esac
case "$(value DEMO_USERS)" in
true|TRUE|1|yes|YES)
error "DEMO_USERS must be false for production."
;;
esac
case "$(value OC_DOCKER_IMAGE)" in
qsfera/qsfera)
;;
"")
warn "OC_DOCKER_IMAGE is empty; compose default must be verified before rollout."
;;
*)
error "OC_DOCKER_IMAGE must be qsfera/qsfera for production."
;;
esac
case "$(value OC_DOCKER_TAG)" in
""|latest|"<"*">")
error "OC_DOCKER_TAG must pin a concrete production release tag."
;;
esac
if ! enabled QSFERA; then
error "QSFERA=:qsfera.yml must be enabled."
fi
if enabled DECOMPOSEDS3; then
require_value DECOMPOSEDS3_ENDPOINT "DECOMPOSEDS3_ENDPOINT"
require_value DECOMPOSEDS3_REGION "DECOMPOSEDS3_REGION"
require_secret DECOMPOSEDS3_ACCESS_KEY
require_secret DECOMPOSEDS3_SECRET_KEY
require_value DECOMPOSEDS3_BUCKET "DECOMPOSEDS3_BUCKET"
fi
if enabled DECOMPOSEDS3_MINIO; then
error "DECOMPOSEDS3_MINIO is for test/lab installs and must not be enabled for public production."
fi
if enabled KEYCLOAK; then
require_value KEYCLOAK_DOMAIN "KEYCLOAK_DOMAIN"
require_value KEYCLOAK_REALM "KEYCLOAK_REALM"
require_secret KEYCLOAK_POSTGRES_PASSWORD
require_value KEYCLOAK_ADMIN_USER "KEYCLOAK_ADMIN_USER"
require_secret KEYCLOAK_ADMIN_PASSWORD
fi
if [ -z "$(value OC_CONFIG_DIR)" ] || [ -z "$(value OC_DATA_DIR)" ]; then
warn "OC_CONFIG_DIR and OC_DATA_DIR are not both set; docker volumes are harder to back up and restore."
fi
if [ "$errors" -gt 0 ]; then
echo "Production env validation failed: $errors error(s), $warnings warning(s)." >&2
exit 1
fi
echo "Production env validation passed: $warnings warning(s)."