#!/bin/sh set -eu repo=$(CDPATH= cd -- "$(dirname "$0")/.." && pwd) cd "$repo" env_file=${COMPOSE_ENV_FILE:-.env.production} online=${1:-} fail() { printf 'FAIL %s\n' "$1" >&2; exit 1; } read_env() { sed -n "s/^$1=//p" "$env_file" | tail -n 1 | sed "s/^'//;s/'$//"; } [ -r "$env_file" ] || fail "$env_file is not readable" if grep -Eq '=(replace-|change-me|example|changeme)' "$env_file"; then fail "placeholder secret remains in $env_file"; fi site=$(read_env SITE_DOMAIN) files=$(read_env FILES_DOMAIN) root_user=$(read_env MINIO_ROOT_USER) root_password=$(read_env MINIO_ROOT_PASSWORD) app_user=$(read_env S3_ACCESS_KEY) app_password=$(read_env S3_SECRET_KEY) [ -n "$site" ] && [ -n "$files" ] || fail "SITE_DOMAIN/FILES_DOMAIN missing" [ "$root_user" != "$app_user" ] || fail "MinIO root and app users must differ" [ "$root_password" != "$app_password" ] || fail "MinIO root and app passwords must differ" docker compose --env-file "$env_file" -f compose.production.yaml config --quiet printf 'OK environment and Compose configuration\n' [ "$online" = "--online" ] || exit 0 site_ip=$(getent ahostsv4 "$site" | awk 'NR==1 {print $1}') files_ip=$(getent ahostsv4 "$files" | awk 'NR==1 {print $1}') [ -n "$site_ip" ] && [ "$site_ip" = "$files_ip" ] || fail "DNS A records are missing or point to different hosts" for domain in "$site" "$files"; do openssl s_client -servername "$domain" -connect "$domain:443" /dev/null | openssl x509 -noout -checkhost "$domain" >/dev/null || fail "TLS hostname mismatch: $domain" done curl -fsS --max-time 15 "https://$site/health" >/dev/null || fail "public health failed" curl -fsS --max-time 15 "https://$site/ready" | grep -Eq '"status"[[:space:]]*:[[:space:]]*"ready"' || fail "public readiness failed" curl -fsS --max-time 15 "https://$files/minio/health/live" >/dev/null || fail "public storage health failed" printf 'OK DNS, TLS and public health (%s)\n' "$site_ip"