156 lines
3.7 KiB
Bash
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)."
|