Files
glchat/scripts/test-install.sh
T
grendervill b9d458e133 fix(cli,web): команды аккаунтов в CLI и повтор запросов при 429
- deploy/glchat-cli.sh: reset-password/make-admin/remove-admin больше не
  заглушки «появится в фазе 1» (AGENT.md 10.7), добавлены totp-setup,
  totp-reset и delete-user; подкоманды обслуживания идут через общий app_cli
- cmd/glchat: команда delete-user (мягкое удаление как в админ-панели,
  защита от удаления инстанс-админа и подтверждение --yes), исправлен
  потерянный комментарий cliCleanup
- deploy/install.sh: убраны устаревшие формулировки про фазу 1
- web: политика повторов запросов — 429 повторяется с паузой retry_after_ms
  (до двух раз, не дольше 5 с), 4xx не повторяются; тесты web/tests/queryRetry.test.ts
- scripts/test-install.sh: проверка, что заглушек в CLI не осталось
2026-09-26 18:32:51 +03:00

153 lines
7.5 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# Прогон deploy/install.sh в чистом контейнере Ubuntu 24.04 (AGENT.md 11.3).
# Требуется Docker с поддержкой привилегированных контейнеров (systemd внутри).
set -euo pipefail
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
IMAGE="${GLCHAT_TEST_IMAGE:-jrei/systemd-ubuntu:24.04}"
CONTAINER="${GLCHAT_TEST_CONTAINER:-glchat-install-test-$$}"
log() { printf '\n=== %s ===\n' "$*"; }
cleanup() {
docker rm -f "$CONTAINER" >/dev/null 2>&1 || true
}
trap cleanup EXIT
log "запуск ${IMAGE} как systemd-контейнера"
docker rm -f "$CONTAINER" >/dev/null 2>&1 || true
docker run -d --name "$CONTAINER" \
--privileged \
--cgroupns=host \
--tmpfs /tmp:exec,size=2g --tmpfs /run --tmpfs /run/lock \
-v /sys/fs/cgroup:/sys/fs/cgroup:rw \
"$IMAGE" /sbin/init >/dev/null
log "ожидание systemd"
for _ in $(seq 1 30); do
if docker exec "$CONTAINER" systemctl is-system-running 2>/dev/null | grep -qE 'running|degraded'; then
break
fi
sleep 1
done
docker exec "$CONTAINER" systemctl is-system-running || true
docker exec "$CONTAINER" bash -lc '. /etc/os-release && echo "тестовое окружение: $PRETTY_NAME"'
log "копируем репозиторий внутрь контейнера"
docker exec "$CONTAINER" mkdir -p /opt/glchat-src
docker cp "${REPO_DIR}/." "${CONTAINER}:/opt/glchat-src/"
# stdin закрыт: иначе установщик может ждать интерактивного подтверждения.
run_install() {
local label="$1"
shift
log "$label"
if ! timeout 1500 docker exec -i "$CONTAINER" bash -lc "
cd /opt/glchat-src && GLCHAT_ETC_DIR=/opt/glchat \
bash deploy/install.sh --domain gl.test.local --email admin@gl.test.local \
--admin admin@gl.test.local --password 'test-password-123' \
--skip-tls --skip-image --app-port 8080 --no-turn --yes $*
" </dev/null; then
echo "install.sh завершился с ошибкой (${label})" >&2
docker exec "$CONTAINER" bash -lc 'tail -40 /opt/glchat/install.log 2>/dev/null || true' || true
exit 1
fi
}
log "1/4 install.sh --dry-run"
timeout 600 docker exec -i "$CONTAINER" bash -lc '
cd /opt/glchat-src && GLCHAT_ETC_DIR=/tmp/dryrun \
bash deploy/install.sh --dry-run --domain gl.test.local --email admin@gl.test.local \
--admin admin@gl.test.local --password "test-password-123" --yes
' </dev/null
run_install "2/5 install.sh (боевой прогон: TLS и публичные порты не трогаем)"
# Секреты обязаны переживать повторную установку: MASTER_KEY расшифровывает
# PII и TOTP, SESSION_PEPPER — blind index. Их смена ломает данные инстанса.
log "3/5 секреты до повторного запуска"
secrets_before="$(docker exec "$CONTAINER" bash -lc '
grep -E "^(MASTER_KEY|SESSION_PEPPER|TOTP_ENCRYPTION_KEY|WEBHOOK_SECRET|LIVEKIT_API_SECRET|AGE_RECIPIENT)=" /opt/glchat/.env | sort
')"
printf '%s\n' "$secrets_before"
# Внешний TURN-релей: в livekit.yaml должны попасть UDP-адрес и TLS-имя хоста
# (сертификат выписан на домен, поэтому TLS-эндпоинт анонсируется именем).
run_install "4/5 идемпотентность: повторный запуск с --reconfigure" --reconfigure \
--turn-relay-host 203.0.113.10 --turn-relay-tls-host turn.gl.test.local
log "4b/5 адреса TURN-релея в livekit.yaml"
relay_rendered="$(docker exec "$CONTAINER" bash -lc 'cat /opt/glchat/livekit/livekit.yaml')"
printf '%s\n' "$relay_rendered" | grep -A 3 "turn_servers" | head -12
for expected in "host: 203.0.113.10" "protocol: udp" "host: turn.gl.test.local" "protocol: tls"; do
if ! printf '%s\n' "$relay_rendered" | grep -q "$expected"; then
echo "ОШИБКА: в livekit.yaml нет строки \"$expected\"" >&2
exit 1
fi
done
echo "адреса TURN-релея отрендерены: ok"
log "5/5 секреты после повторного запуска"
secrets_after="$(docker exec "$CONTAINER" bash -lc '
grep -E "^(MASTER_KEY|SESSION_PEPPER|TOTP_ENCRYPTION_KEY|WEBHOOK_SECRET|LIVEKIT_API_SECRET|AGE_RECIPIENT)=" /opt/glchat/.env | sort
')"
printf '%s\n' "$secrets_after"
if [ "$secrets_before" != "$secrets_after" ]; then
echo "ОШИБКА: повторный запуск установщика изменил секреты (данные станут нечитаемыми)" >&2
diff <(printf '%s\n' "$secrets_before") <(printf '%s\n' "$secrets_after") >&2 || true
exit 1
fi
echo "секреты сохранены при повторной установке: ok"
# Offsite-бэкапы: ключи должны присутствовать в .env сразу после установки
# (пустыми — цель задаёт владелец), иначе backup.sh не увидит настройку.
log "offsite-настройки в .env"
docker exec "$CONTAINER" bash -lc '
set -e
for key in BACKUP_KEEP_DAYS BACKUP_OFFSITE_TARGET BACKUP_OFFSITE_KEEP_DAYS AGE_RECIPIENT; do
grep -q "^${key}=" /opt/glchat/.env || { echo "нет ${key} в .env" >&2; exit 1; }
echo "${key}: ok"
done
'
# Сборка образа внутри DinD невозможна (overlay поверх overlay), поэтому образ
# собирается и проверяется отдельно на хосте (make docker-build + docker compose).
log "проверки состояния установки"
docker exec "$CONTAINER" bash -lc '
set -e
echo "--- артефакты ---"
test -x /usr/local/bin/glchat && echo "CLI: ok"
test -f /opt/glchat/compose.yaml && echo "compose: ok"
test -f /opt/glchat/caddy/Caddyfile && echo "Caddyfile: ok"
test -f /opt/glchat/livekit/livekit.yaml && echo "livekit.yaml: ok"
test -f /opt/glchat/nftables/glchat.nft && echo "nftables: ok"
test -f /opt/glchat/fail2ban/jail.local && echo "fail2ban jail: ok"
test -f /opt/glchat/glchat.service && echo "systemd unit: ok"
stat -c "perms %a %n" /opt/glchat/.env
echo "--- плейсхолдеры в конфигах (должно быть 0) ---"
grep -c "{{" /opt/glchat/compose.yaml /opt/glchat/livekit/livekit.yaml /opt/glchat/caddy/Caddyfile || true
echo "--- сервисы ---"
systemctl is-enabled glchat.service
systemctl is-active fail2ban
systemctl is-enabled glchat-nftables.service
systemctl is-enabled glchat-docker-user.service
echo "--- ufw ---"
ufw status | head -8
echo "--- fail2ban jails ---"
fail2ban-client status
echo "--- glchat CLI ---"
glchat version
# Команды аккаунтов живут в Go-бинарнике: в обёртке не должно остаться
# заглушек «появится в фазе 1», а справка обязана их перечислять.
grep -q "delete-user" /usr/local/bin/glchat && echo "CLI: команды аккаунтов: ok"
glchat help | grep -q "reset-password" && echo "CLI: справка аккаунтов: ok"
if grep -q "появится в фазе 1" /usr/local/bin/glchat; then
echo "CLI: в обёртке осталась заглушка фазы 1" >&2
exit 1
fi
echo "--- конфиги валидны ---"
docker compose -f /opt/glchat/compose.yaml config -q && echo "compose config: valid"
'
log "ОК: прогон установщика в чистом Ubuntu 24.04 завершён"