feat: add production deployment preflight
This commit is contained in:
@@ -25,6 +25,12 @@ docker run --rm caddy:2.10.2-alpine caddy hash-password --plaintext 'ОТДЕЛ
|
||||
|
||||
## 3. Проверка и первый запуск
|
||||
|
||||
Перед первым запуском проверьте секреты и итоговую Compose-конфигурацию, не выводя значения в лог:
|
||||
|
||||
```bash
|
||||
./deploy/preflight.sh
|
||||
```
|
||||
|
||||
```bash
|
||||
docker compose --env-file .env.production -f compose.production.yaml config --quiet
|
||||
docker compose --env-file .env.production -f compose.production.yaml build
|
||||
@@ -34,6 +40,12 @@ curl -fsS https://rf4spotter.ru/health
|
||||
curl -fsS https://rf4spotter.ru/ready
|
||||
```
|
||||
|
||||
После обновления DNS и получения сертификатов выполните внешний этап той же проверки:
|
||||
|
||||
```bash
|
||||
./deploy/preflight.sh --online
|
||||
```
|
||||
|
||||
До запуска на сервере можно воспроизвести полный production bootstrap на пустых изолированных volumes. Скрипт собирает образы, применяет миграции, проверяет отсутствие демо-уловов, readiness и отправку заявки:
|
||||
|
||||
```bash
|
||||
|
||||
Executable
+38
@@ -0,0 +1,38 @@
|
||||
#!/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 2>/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"
|
||||
Reference in New Issue
Block a user