feat: add production deployment preflight

This commit is contained in:
ik
2026-09-07 09:18:22 +07:00
parent d69ad9c01d
commit 2aa2d30750
4 changed files with 53 additions and 2 deletions
+12
View File
@@ -25,6 +25,12 @@ docker run --rm caddy:2.10.2-alpine caddy hash-password --plaintext 'ОТДЕЛ
## 3. Проверка и первый запуск ## 3. Проверка и первый запуск
Перед первым запуском проверьте секреты и итоговую Compose-конфигурацию, не выводя значения в лог:
```bash
./deploy/preflight.sh
```
```bash ```bash
docker compose --env-file .env.production -f compose.production.yaml config --quiet docker compose --env-file .env.production -f compose.production.yaml config --quiet
docker compose --env-file .env.production -f compose.production.yaml build 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 curl -fsS https://rf4spotter.ru/ready
``` ```
После обновления DNS и получения сертификатов выполните внешний этап той же проверки:
```bash
./deploy/preflight.sh --online
```
До запуска на сервере можно воспроизвести полный production bootstrap на пустых изолированных volumes. Скрипт собирает образы, применяет миграции, проверяет отсутствие демо-уловов, readiness и отправку заявки: До запуска на сервере можно воспроизвести полный production bootstrap на пустых изолированных volumes. Скрипт собирает образы, применяет миграции, проверяет отсутствие демо-уловов, readiness и отправку заявки:
```bash ```bash
+38
View File
@@ -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"
+1 -1
View File
@@ -81,7 +81,7 @@
- [ ] Добавить smoke-проверку административной очереди внешних источников на desktop/mobile без публикации реальных записей. - [ ] Добавить smoke-проверку административной очереди внешних источников на desktop/mobile без публикации реальных записей.
- [ ] Обновить README: архитектура, все переменные окружения, импорт, модерация, backup/restore, эксплуатация логов и известные ограничения. - [ ] Обновить README: архитектура, все переменные окружения, импорт, модерация, backup/restore, эксплуатация логов и известные ограничения.
- [ ] Выбрать лицензию кода и политику использования данных. - [ ] Выбрать лицензию кода и политику использования данных.
- [ ] Завершить production-профиль для `rf4spotter.ru`: приложение готово; внешняя проверка 6 сентября выявила неверный сертификат `*.timeweb.ru` на корневом домене и отсутствие DNS для `files.rf4spotter.ru`; требуются IP целевого сервера, DNS, запуск и канал уведомлений (`docs/deployment-status.md`). - [ ] Завершить production-профиль для `rf4spotter.ru`: приложение и `deploy/preflight.sh` готовы; внешняя проверка 7 сентября не установила соединение с обоими доменами, требуются IP целевого сервера, DNS, запуск и канал уведомлений (`docs/deployment-status.md`).
- [ ] Заменить демонстрационные секреты и определить целевое размещение перед внешней публикацией. - [ ] Заменить демонстрационные секреты и определить целевое размещение перед внешней публикацией.
## Источники данных и согласование ## Источники данных и согласование
+2 -1
View File
@@ -1,6 +1,6 @@
# Статус развёртывания rf4spotter.ru # Статус развёртывания rf4spotter.ru
Последняя внешняя read-only проверка: 6 сентября 2026 года. Последняя внешняя read-only проверка: 7 сентября 2026 года. Web-клиент не смог установить соединение ни с корневым доменом, ни с `files`; прежние DNS/TLS-блокеры считаются незакрытыми до успешного `deploy/preflight.sh --online` на целевом сервере.
## Что видно публично сейчас ## Что видно публично сейчас
@@ -25,5 +25,6 @@
- [ ] Убедиться, что Caddy получил сертификаты с SAN `rf4spotter.ru` и `files.rf4spotter.ru`. - [ ] Убедиться, что Caddy получил сертификаты с SAN `rf4spotter.ru` и `files.rf4spotter.ru`.
- [ ] Выполнить `curl` для `/`, `/health`, `/ready` и MinIO health через оба домена. - [ ] Выполнить `curl` для `/`, `/health`, `/ready` и MinIO health через оба домена.
- [ ] Создать первую внешнюю резервную копию, запустить `deploy/monitor.sh` и подключить уведомления. - [ ] Создать первую внешнюю резервную копию, запустить `deploy/monitor.sh` и подключить уведомления.
- [x] Добавить единый preflight без вывода секретов: проверка env/Compose до запуска и DNS/TLS/health после запуска (`deploy/preflight.sh`).
Не следует отключать TLS verification или сохранять текущий чужой сертификат в исключения: после правильных DNS и доступных портов Caddy должен получить корректный сертификат автоматически. Не следует отключать TLS verification или сохранять текущий чужой сертификат в исключения: после правильных DNS и доступных портов Caddy должен получить корректный сертификат автоматически.