fix and update
This commit is contained in:
156
install.sh
156
install.sh
@@ -10,7 +10,7 @@
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_VERSION="2.6.3"
|
||||
SCRIPT_VERSION="2.6.4"
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "$ROOT_DIR"
|
||||
|
||||
@@ -432,6 +432,7 @@ action_fix_docker_nginx() {
|
||||
|
||||
log "Восстановление Docker Nginx (lendry-id-nginx)..."
|
||||
ensure_docker_nginx_mode_for_fix_all
|
||||
ensure_docker_nginx_configs
|
||||
prepare_compose_stack
|
||||
ensure_nginx_after_stack_rebuild || fail "Не удалось запустить lendry-id-nginx"
|
||||
sync_nginx_after_api_gateway_restart || true
|
||||
@@ -471,6 +472,7 @@ wait_for_api_gateway_http() {
|
||||
# После recreate api-gateway nginx должен сбросить DNS/keepalive — иначе 502 на старый IP.
|
||||
sync_nginx_after_api_gateway_restart() {
|
||||
docker_nginx_container_running || return 0
|
||||
ensure_docker_nginx_configs || true
|
||||
log "Синхронизация Docker Nginx с api-gateway после пересборки..."
|
||||
wait_for_service "api-gateway" 120 || warn "api-gateway не стал healthy в срок"
|
||||
wait_for_api_gateway_http 90 || warn "api-gateway /health на :3000 не отвечает"
|
||||
@@ -522,6 +524,7 @@ ensure_nginx_after_stack_rebuild() {
|
||||
|
||||
if [[ "$(env_get NGINX_MODE docker)" == "docker" ]]; then
|
||||
log "Запуск и синхронизация Docker Nginx (lendry-id-nginx)..."
|
||||
ensure_docker_nginx_configs
|
||||
ensure_nginx_gateway_watch_script
|
||||
patch_legacy_nginx_proxy_pass || true
|
||||
|
||||
@@ -572,10 +575,19 @@ nginx_probe_idp_api_health_from_container() {
|
||||
build_compose_stack_cmd
|
||||
|
||||
if [[ "$use_ssl" == "true" || "$ssl_type" != "none" ]]; then
|
||||
docker_cmd "${COMPOSE_STACK_CMD[@]}" exec -T nginx \
|
||||
body="$(docker_cmd "${COMPOSE_STACK_CMD[@]}" exec -T nginx \
|
||||
wget -qO- --timeout=6 --no-check-certificate \
|
||||
--header="Host: ${frontend_domain}" \
|
||||
"https://127.0.0.1/idp-api/health" 2>/dev/null || true
|
||||
"https://127.0.0.1/idp-api/health" 2>/dev/null || true)"
|
||||
if [[ "$body" == *'"status"'* ]]; then
|
||||
printf '%s' "$body"
|
||||
return 0
|
||||
fi
|
||||
body="$(docker_cmd "${COMPOSE_STACK_CMD[@]}" exec -T nginx \
|
||||
wget -qO- --timeout=6 \
|
||||
--header="Host: ${frontend_domain}" \
|
||||
"http://127.0.0.1/idp-api/health" 2>/dev/null || true)"
|
||||
printf '%s' "$body"
|
||||
return 0
|
||||
fi
|
||||
|
||||
@@ -1635,6 +1647,7 @@ action_migrate_rebuild() {
|
||||
wait_for_service docs 60
|
||||
|
||||
log "Шаг 4/4: Nginx, прокси и проверка..."
|
||||
ensure_docker_nginx_configs
|
||||
ensure_nginx_after_stack_rebuild || warn "Nginx не восстановлен — выполните: ./install.sh --fix-docker-nginx"
|
||||
post_deploy_proxy_verify 0 || warn "HTTPS-проверка не прошла — выполните: ./install.sh --fix-all"
|
||||
diagnose_common_issues || true
|
||||
@@ -3014,7 +3027,7 @@ verify_nginx_reaches_api_gateway() {
|
||||
wget -qO- --timeout=5 http://api-gateway:3000/health 2>/dev/null || true)"
|
||||
if [[ "$body" == *'"status":"ok"'* ]] || [[ "$body" == *'"status": "ok"'* ]]; then
|
||||
ok "Docker Nginx → api-gateway:3000/health OK (IP api-gateway: ${gw_ip:-?})"
|
||||
verify_nginx_idp_api_location || return 1
|
||||
verify_nginx_idp_api_location || warn "location /idp-api/ — проверьте SSL и nginx/conf.d (upstream OK)"
|
||||
return 0
|
||||
fi
|
||||
attempt=$((attempt + 1))
|
||||
@@ -3051,17 +3064,22 @@ verify_nginx_idp_api_location() {
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Fallback: проверка с хоста (как curl из браузера / DevTools)
|
||||
# Fallback: проверка через локальный Docker Nginx (127.0.0.1), без DNS на сервере
|
||||
if [[ "$(env_get USE_NGINX_SSL false)" == "true" || "$ssl_type" != "none" ]]; then
|
||||
code="$(curl -sk --max-time 6 -o /dev/null -w '%{http_code}' "https://${frontend_domain}/idp-api/health" 2>/dev/null || echo 000)"
|
||||
code="$(curl_local_nginx_code "$frontend_domain" "/idp-api/health" 1 6)"
|
||||
else
|
||||
code="$(curl -fsS --max-time 6 -o /dev/null -w '%{http_code}' "http://${frontend_domain}/idp-api/health" 2>/dev/null || echo 000)"
|
||||
code="$(curl_local_nginx_code "$frontend_domain" "/idp-api/health" 0 6)"
|
||||
fi
|
||||
if [[ "$code" == "200" ]]; then
|
||||
ok "SSO /idp-api/health → 200 (проверка с хоста; внутри контейнера — см. SSL/301)"
|
||||
ok "SSO /idp-api/health → 200 (через lendry-id-nginx на 127.0.0.1)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if ! docker_nginx_configs_present; then
|
||||
warn "nginx/conf.d пуст — выполните: ./install.sh --fix-all"
|
||||
return 1
|
||||
fi
|
||||
|
||||
warn "Nginx location /idp-api/ не проксирует на api-gateway (Host: ${frontend_domain}, HTTP ${code:-?})"
|
||||
warn "Проверьте: curl -sk https://${frontend_domain}/idp-api/health"
|
||||
warn " и: docker compose --env-file .env --profile proxy exec nginx wget -qO- --no-check-certificate --header=\"Host: ${frontend_domain}\" https://127.0.0.1/idp-api/health"
|
||||
@@ -3086,7 +3104,7 @@ verify_nginx_reaches_frontend() {
|
||||
if [[ -n "$body" ]]; then
|
||||
ok "Docker Nginx → frontend:3000/ OK (IP frontend: ${fe_ip:-?})"
|
||||
if [[ -n "$frontend_domain" ]]; then
|
||||
verify_nginx_frontend_root_location "$frontend_domain" || return 1
|
||||
verify_nginx_frontend_root_location "$frontend_domain" || warn "location / — проверьте SSL и nginx/conf.d (upstream OK)"
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
@@ -3116,16 +3134,30 @@ verify_nginx_frontend_root_location() {
|
||||
return 0
|
||||
fi
|
||||
|
||||
body="$(docker_cmd "${COMPOSE_STACK_CMD[@]}" exec -T nginx \
|
||||
wget -qO- --timeout=8 \
|
||||
--header="Host: ${frontend_domain}" \
|
||||
"http://127.0.0.1/" 2>/dev/null | head -c 256 || true)"
|
||||
if [[ -n "$body" ]]; then
|
||||
ok "Docker Nginx location / → frontend OK по HTTP (Host: ${frontend_domain})"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ "$(env_get USE_NGINX_SSL false)" == "true" || "$ssl_type" != "none" ]]; then
|
||||
code="$(curl -sk --max-time 8 -o /dev/null -w '%{http_code}' "https://${frontend_domain}/" 2>/dev/null || echo 000)"
|
||||
code="$(curl_local_nginx_code "$frontend_domain" "/" 1 8)"
|
||||
else
|
||||
code="$(curl -fsS --max-time 8 -o /dev/null -w '%{http_code}' "http://${frontend_domain}/" 2>/dev/null || echo 000)"
|
||||
code="$(curl_local_nginx_code "$frontend_domain" "/" 0 8)"
|
||||
fi
|
||||
if [[ "$code" == "200" || "$code" == "304" ]]; then
|
||||
ok "SSO / → HTTP ${code} (проверка с хоста)"
|
||||
ok "SSO / → HTTP ${code} (через lendry-id-nginx на 127.0.0.1)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if ! docker_nginx_configs_present; then
|
||||
warn "nginx/conf.d пуст — выполните: ./install.sh --fix-all"
|
||||
return 1
|
||||
fi
|
||||
|
||||
warn "Nginx location / не проксирует на frontend (Host: ${frontend_domain}, HTTP ${code:-?})"
|
||||
warn "Проверьте: curl -sk -o /dev/null -w '%{http_code}' https://${frontend_domain}/"
|
||||
return 1
|
||||
@@ -3139,9 +3171,9 @@ check_sso_frontend_root() {
|
||||
ssl_type="$(env_get SSL_TYPE none)"
|
||||
|
||||
if [[ "$(env_get USE_NGINX_SSL false)" == "true" || "$ssl_type" != "none" ]]; then
|
||||
code="$(curl -sk --max-time 8 -o /dev/null -w '%{http_code}' "https://${frontend_domain}/" 2>/dev/null || echo 000)"
|
||||
code="$(curl_local_nginx_code "$frontend_domain" "/" 1 8)"
|
||||
else
|
||||
code="$(curl -fsS --max-time 8 -o /dev/null -w '%{http_code}' "http://${frontend_domain}/" 2>/dev/null || echo 000)"
|
||||
code="$(curl_local_nginx_code "$frontend_domain" "/" 0 8)"
|
||||
fi
|
||||
|
||||
if [[ "$code" == "200" || "$code" == "304" ]]; then
|
||||
@@ -3193,9 +3225,9 @@ check_sso_idp_api_proxy() {
|
||||
fi
|
||||
|
||||
if [[ "$(env_get USE_NGINX_SSL false)" != "true" ]]; then
|
||||
code="$(curl -fsS --max-time 5 -o /dev/null -w '%{http_code}' "http://${frontend_domain}/idp-api/health" 2>/dev/null || echo 000)"
|
||||
code="$(curl_local_nginx_code "$frontend_domain" "/idp-api/health" 0 5)"
|
||||
else
|
||||
code="$(curl -sk --max-time 5 -o /dev/null -w '%{http_code}' "https://${frontend_domain}/idp-api/health" 2>/dev/null || echo 000)"
|
||||
code="$(curl_local_nginx_code "$frontend_domain" "/idp-api/health" 1 5)"
|
||||
fi
|
||||
|
||||
if [[ "$code" == "200" ]]; then
|
||||
@@ -3711,6 +3743,66 @@ refresh_host_nginx_configs() {
|
||||
esac
|
||||
}
|
||||
|
||||
docker_nginx_configs_present() {
|
||||
[[ -f "${LOCAL_CONF_DIR}/${NGINX_PREFIX}-frontend.conf" ]] \
|
||||
&& [[ -f "${LOCAL_CONF_DIR}/${NGINX_PREFIX}-api.conf" ]]
|
||||
}
|
||||
|
||||
# Генерирует ./nginx/conf.d при переходе с host Nginx или первом запуске Docker Nginx.
|
||||
ensure_docker_nginx_configs() {
|
||||
load_env
|
||||
[[ "$(env_get NGINX_MODE docker)" == "docker" ]] || return 0
|
||||
[[ -n "$(env_get DOMAIN_API "")" && -n "$(env_get DOMAIN_FRONTEND "")" ]] || return 0
|
||||
[[ "$(env_get INSTALL_MODE local)" == "local" ]] && return 0
|
||||
docker_nginx_configs_present && return 0
|
||||
|
||||
warn "Конфиги Docker Nginx отсутствуют в ${LOCAL_CONF_DIR} — генерируем..."
|
||||
DOMAIN_API="$(env_get DOMAIN_API "")"
|
||||
DOMAIN_FRONTEND="$(env_get DOMAIN_FRONTEND "")"
|
||||
DOMAIN_DOCS="$(env_get DOMAIN_DOCS "")"
|
||||
DOMAIN_WS="$(env_get DOMAIN_WS "")"
|
||||
DOMAIN_MINIO="$(env_get DOMAIN_MINIO "")"
|
||||
DOMAIN_MINIO_CONSOLE="$(env_get DOMAIN_MINIO_CONSOLE "")"
|
||||
NGINX_MODE="docker"
|
||||
FORCE_DOCKER_NGINX=1
|
||||
|
||||
local ssl_type
|
||||
ssl_type="$(env_get SSL_TYPE none)"
|
||||
case "$ssl_type" in
|
||||
none)
|
||||
write_nginx_http_only
|
||||
;;
|
||||
custom)
|
||||
install_custom_certificates || warn "Не удалось установить custom-сертификаты"
|
||||
write_all_nginx_configs "custom"
|
||||
;;
|
||||
selfsigned)
|
||||
generate_all_self_signed_certs || warn "Не удалось создать self-signed сертификаты"
|
||||
write_all_nginx_configs "selfsigned"
|
||||
;;
|
||||
letsencrypt)
|
||||
write_all_nginx_configs "letsencrypt"
|
||||
;;
|
||||
*)
|
||||
write_nginx_http_only
|
||||
;;
|
||||
esac
|
||||
ok "Конфиги Docker Nginx записаны в ${LOCAL_CONF_DIR}"
|
||||
}
|
||||
|
||||
# HTTP-код через локальный lendry-id-nginx (--resolve 127.0.0.1, без DNS домена на сервере).
|
||||
curl_local_nginx_code() {
|
||||
local domain="$1" path="$2" use_ssl="${3:-1}" timeout="${4:-8}"
|
||||
local port=443
|
||||
local -a curl_opts=(-sk --max-time "$timeout" -o /dev/null -w '%{http_code}')
|
||||
if [[ "$use_ssl" != "1" ]]; then
|
||||
port=80
|
||||
curl_opts=(-fsS --max-time "$timeout" -o /dev/null -w '%{http_code}')
|
||||
fi
|
||||
curl "${curl_opts[@]}" --resolve "${domain}:${port}:127.0.0.1" \
|
||||
"$([[ "$use_ssl" == "1" ]] && echo "https" || echo "http")://${domain}${path}" 2>/dev/null || echo 000
|
||||
}
|
||||
|
||||
check_local_upstream() {
|
||||
local label="$1" url="$2"
|
||||
if curl -fsS --max-time 3 "$url" >/dev/null 2>&1; then
|
||||
@@ -3745,7 +3837,8 @@ check_https_api_with_origin() {
|
||||
[[ "$(env_get USE_NGINX_SSL false)" == "true" ]] || return 0
|
||||
|
||||
origin="https://${frontend_domain}"
|
||||
code="$(curl -sk --max-time 5 -o /dev/null -w '%{http_code}' -H "Origin: ${origin}" "https://${api_domain}/health" 2>/dev/null || echo 000)"
|
||||
code="$(curl -sk --max-time 5 -o /dev/null -w '%{http_code}' -H "Origin: ${origin}" \
|
||||
--resolve "${api_domain}:443:127.0.0.1" "https://${api_domain}/health" 2>/dev/null || echo 000)"
|
||||
if [[ "$code" == "200" ]]; then
|
||||
echo -e " ${GREEN}✔${NC} HTTPS API + Origin: https://${api_domain}/health → 200"
|
||||
elif [[ "$code" == "502" ]]; then
|
||||
@@ -3757,7 +3850,8 @@ check_https_api_with_origin() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
code="$(curl -sk --max-time 5 -o /dev/null -w '%{http_code}' -H "Origin: ${origin}" "https://${api_domain}/notifications/unread-count" 2>/dev/null || echo 000)"
|
||||
code="$(curl -sk --max-time 5 -o /dev/null -w '%{http_code}' -H "Origin: ${origin}" \
|
||||
--resolve "${api_domain}:443:127.0.0.1" "https://${api_domain}/notifications/unread-count" 2>/dev/null || echo 000)"
|
||||
if [[ "$code" == "401" || "$code" == "403" ]]; then
|
||||
echo -e " ${GREEN}✔${NC} HTTPS API + Origin (без токена): /notifications/unread-count → ${code}"
|
||||
elif [[ "$code" == "502" ]]; then
|
||||
@@ -3772,6 +3866,7 @@ check_https_api_with_origin() {
|
||||
code="$(curl -sk --max-time 5 -o /dev/null -w '%{http_code}' -X OPTIONS \
|
||||
-H "Origin: ${origin}" \
|
||||
-H "Access-Control-Request-Method: GET" \
|
||||
--resolve "${api_domain}:443:127.0.0.1" \
|
||||
"https://${api_domain}/notifications/unread-count" 2>/dev/null || echo 000)"
|
||||
if [[ "$code" == "204" || "$code" == "200" ]]; then
|
||||
echo -e " ${GREEN}✔${NC} HTTPS API preflight (OPTIONS): /notifications/unread-count → ${code}"
|
||||
@@ -3840,12 +3935,24 @@ diagnose_common_issues() {
|
||||
fi
|
||||
if [[ "$(env_get NGINX_MODE docker)" == "docker" ]]; then
|
||||
shopt -s nullglob
|
||||
if grep -q 'proxy_pass.*\$request_uri' "${LOCAL_CONF_DIR}/${NGINX_PREFIX}-"*.conf 2>/dev/null; then
|
||||
local conf legacy_conf=0
|
||||
for conf in "${LOCAL_CONF_DIR}/${NGINX_PREFIX}-"*.conf; do
|
||||
[[ -f "$conf" ]] || continue
|
||||
if grep -q 'proxy_pass.*\$request_uri' "$conf" 2>/dev/null; then
|
||||
legacy_conf=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
shopt -u nullglob
|
||||
if [[ "$legacy_conf" -eq 1 ]]; then
|
||||
echo -e " ${RED}✘${NC} nginx/conf.d: proxy_pass \$request_uri — 502 на / (no resolver defined to resolve lendry-id-frontend)"
|
||||
echo " Решение: ./install.sh --fix-all"
|
||||
issues=$((issues + 1))
|
||||
elif ! docker_nginx_configs_present; then
|
||||
echo -e " ${RED}✘${NC} nginx/conf.d пуст — Docker Nginx без vhost (502 в браузере)"
|
||||
echo " Решение: ./install.sh --fix-all"
|
||||
issues=$((issues + 1))
|
||||
fi
|
||||
shopt -u nullglob
|
||||
fi
|
||||
elif [[ "$(env_get NGINX_MODE docker)" == "docker" ]] && compose_uses_proxy_profile; then
|
||||
echo -e " ${YELLOW}!${NC} Docker Nginx не запущен (ожидался в режиме docker)"
|
||||
@@ -4271,14 +4378,15 @@ action_fix_all_errors() {
|
||||
echo " (502 Bad Gateway, /idp-api, Docker Nginx lendry-id-nginx, порты upstream)"
|
||||
echo ""
|
||||
|
||||
log "Шаг 1/7: диагностика..."
|
||||
diagnose_common_issues || true
|
||||
|
||||
log "Шаг 2/7: Docker Nginx — остановка system nginx, освобождение 80/443..."
|
||||
log "Шаг 1/7: Docker Nginx — остановка system nginx, конфиги, освобождение 80/443..."
|
||||
ensure_docker_nginx_mode_for_fix_all
|
||||
ensure_docker_nginx_configs
|
||||
write_compose_override
|
||||
ensure_split_domain_public_urls
|
||||
|
||||
log "Шаг 2/7: диагностика..."
|
||||
diagnose_common_issues || true
|
||||
|
||||
log "Шаг 3/7: миграции PostgreSQL (Prisma)..."
|
||||
compose_build_and_up postgres 2>/dev/null || true
|
||||
run_prisma_migrations || warn "Миграции Prisma не применены — sso-core попробует при старте"
|
||||
|
||||
Reference in New Issue
Block a user