fix and update
This commit is contained in:
252
install.sh
252
install.sh
@@ -10,7 +10,7 @@
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_VERSION="2.2.5"
|
||||
SCRIPT_VERSION="2.3.0"
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "$ROOT_DIR"
|
||||
|
||||
@@ -73,6 +73,7 @@ ${BOLD}Lendry ID v${SCRIPT_VERSION}${NC} — установка и управл
|
||||
./install.sh --restart Перезапуск контейнеров
|
||||
./install.sh --docker-prune Только очистка Docker (без пересборки)
|
||||
./install.sh --fix-proxy Исправить 502: host Nginx + порты 3000/3002/3003
|
||||
./install.sh --fix-all Комплексное исправление: 502, прокси, порты, Nginx
|
||||
./install.sh --status Статус сервисов
|
||||
./install.sh --reset-db Сброс PostgreSQL (новый пароль из .env, данные удалятся)
|
||||
./install.sh --remove-nginx Удалить конфиги Nginx IdP
|
||||
@@ -146,6 +147,7 @@ parse_args() {
|
||||
--skip-docker-prune) SKIP_DOCKER_PRUNE=1; shift ;;
|
||||
--docker-prune-aggressive) DOCKER_PRUNE_AGGRESSIVE=1; shift ;;
|
||||
--fix-proxy) ACTION="fix-proxy"; shift ;;
|
||||
--fix-all) ACTION="fix-all"; shift ;;
|
||||
--status) ACTION="status"; shift ;;
|
||||
--reset-db) ACTION="reset-db"; shift ;;
|
||||
--local) INSTALL_LOCAL=1; shift ;;
|
||||
@@ -253,6 +255,45 @@ lendry_host_nginx_configured() {
|
||||
|| [[ -L "${NGINX_ENABLED}/${NGINX_PREFIX}-frontend.conf" ]]
|
||||
}
|
||||
|
||||
docker_nginx_container_running() {
|
||||
docker_cmd ps -q -f name=lendry-id-nginx 2>/dev/null | grep -q .
|
||||
}
|
||||
|
||||
docker_nginx_ports_available() {
|
||||
local http="${NGINX_HTTP_PORT:-80}"
|
||||
local https="${NGINX_HTTPS_PORT:-443}"
|
||||
! port_in_use "$http" && ! port_in_use "$https"
|
||||
}
|
||||
|
||||
# Не даём контейнерному nginx занять 80/443, если их уже держит системный nginx
|
||||
# или явно выбран NGINX_MODE=host (типичная причина «address already in use»).
|
||||
ensure_docker_nginx_not_conflicting() {
|
||||
load_env
|
||||
resolve_nginx_mode_and_ports
|
||||
|
||||
local http="${NGINX_HTTP_PORT:-80}"
|
||||
local https="${NGINX_HTTPS_PORT:-443}"
|
||||
local ports_busy=0
|
||||
port_in_use "$http" && ports_busy=1
|
||||
port_in_use "$https" && ports_busy=1
|
||||
|
||||
if [[ "$ports_busy" -eq 1 ]] && [[ "$(env_get NGINX_MODE docker)" == "docker" ]]; then
|
||||
if host_nginx_available || system_nginx_is_active || lendry_host_nginx_configured; then
|
||||
warn "Порты ${http}/${https} заняты системным Nginx — переключаем NGINX_MODE на host"
|
||||
warn "Контейнер lendry-id-nginx не будет запущен (используйте системный Nginx)"
|
||||
NGINX_MODE="host"
|
||||
env_set NGINX_MODE "host"
|
||||
else
|
||||
warn "Порты ${http}/${https} заняты другим процессом — Docker Nginx не сможет стартовать"
|
||||
warn "Освободите порты или укажите другие: --nginx-http-port / --nginx-https-port"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$(env_get NGINX_MODE docker)" == "host" ]] || [[ "$ports_busy" -eq 1 ]]; then
|
||||
stop_docker_nginx
|
||||
fi
|
||||
}
|
||||
|
||||
stop_docker_nginx() {
|
||||
local cid
|
||||
cid="$(docker_cmd ps -q -f name=lendry-id-nginx 2>/dev/null || true)"
|
||||
@@ -267,10 +308,7 @@ stop_docker_nginx() {
|
||||
prepare_compose_stack() {
|
||||
resolve_nginx_mode_and_ports
|
||||
write_compose_override
|
||||
load_env
|
||||
if [[ "$(env_get NGINX_MODE docker)" == "host" ]]; then
|
||||
stop_docker_nginx
|
||||
fi
|
||||
ensure_docker_nginx_not_conflicting
|
||||
}
|
||||
|
||||
resolve_nginx_mode_and_ports() {
|
||||
@@ -299,7 +337,7 @@ resolve_nginx_mode_and_ports() {
|
||||
|
||||
if [[ "$NGINX_MODE" == "docker" ]]; then
|
||||
if port_in_use "$NGINX_HTTP_PORT" || port_in_use "$NGINX_HTTPS_PORT"; then
|
||||
if host_nginx_available && [[ "$NGINX_HTTP_PORT" == "80" ]]; then
|
||||
if host_nginx_available || system_nginx_is_active || lendry_host_nginx_configured; then
|
||||
warn "Порт ${NGINX_HTTP_PORT}/${NGINX_HTTPS_PORT} занят — переключаемся на системный Nginx (host)"
|
||||
NGINX_MODE="host"
|
||||
env_set NGINX_MODE "host"
|
||||
@@ -350,6 +388,9 @@ compose_uses_proxy_profile() {
|
||||
[[ -n "$(env_get DOMAIN_API "")" ]] || return 1
|
||||
[[ "$(env_get INSTALL_MODE local)" == "local" ]] && return 1
|
||||
[[ "$(env_get NGINX_MODE docker)" == "docker" ]] || return 1
|
||||
if ! docker_nginx_ports_available; then
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -529,9 +570,27 @@ compose_build_and_up() {
|
||||
fi
|
||||
|
||||
configure_docker_build_env
|
||||
ensure_docker_nginx_not_conflicting
|
||||
build_compose_stack_cmd
|
||||
compose_build_parallel_flags
|
||||
|
||||
if [[ ${#services[@]} -gt 0 ]]; then
|
||||
local -a filtered=()
|
||||
local svc
|
||||
for svc in "${services[@]}"; do
|
||||
if [[ "$svc" == "nginx" ]] && ! compose_uses_proxy_profile; then
|
||||
warn "Пропуск сервиса nginx: порты заняты или NGINX_MODE=host — используйте системный Nginx"
|
||||
continue
|
||||
fi
|
||||
filtered+=("$svc")
|
||||
done
|
||||
services=("${filtered[@]}")
|
||||
if [[ ${#services[@]} -eq 0 ]]; then
|
||||
warn "Нет сервисов для запуска после проверки конфликта Nginx"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "${SKIP_DOCKER_PRUNE:-0}" -ne 1 ]]; then
|
||||
docker_prune_before_rebuild "${DOCKER_PRUNE_AGGRESSIVE:-0}"
|
||||
fi
|
||||
@@ -548,6 +607,8 @@ compose_build_and_up() {
|
||||
docker_cmd "${COMPOSE_STACK_CMD[@]}" up -d --remove-orphans
|
||||
fi
|
||||
|
||||
ensure_docker_nginx_not_conflicting
|
||||
|
||||
if [[ "${SKIP_DOCKER_PRUNE:-0}" -ne 1 ]]; then
|
||||
docker_prune_after_rebuild
|
||||
fi
|
||||
@@ -2309,9 +2370,7 @@ setup_nginx_proxy() {
|
||||
|
||||
resolve_nginx_mode_and_ports
|
||||
write_compose_override
|
||||
if [[ "$(env_get NGINX_MODE docker)" == "host" ]]; then
|
||||
stop_docker_nginx
|
||||
fi
|
||||
ensure_docker_nginx_not_conflicting
|
||||
install_nginx_certbot
|
||||
|
||||
local ssl_type
|
||||
@@ -2494,11 +2553,90 @@ check_local_upstream() {
|
||||
local label="$1" url="$2"
|
||||
if curl -fsS --max-time 3 "$url" >/dev/null 2>&1; then
|
||||
echo -e " ${GREEN}✔${NC} ${label}: ${url}"
|
||||
return 0
|
||||
else
|
||||
echo -e " ${RED}✘${NC} ${label}: ${url} — недоступен"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Диагностика типичных проблем: 502 на /idp-api, конфликт nginx, порты upstream.
|
||||
diagnose_common_issues() {
|
||||
load_env
|
||||
local issues=0
|
||||
|
||||
echo ""
|
||||
echo -e "${BOLD}Диагностика${NC}"
|
||||
echo ""
|
||||
|
||||
if docker_nginx_container_running; then
|
||||
if [[ "$(env_get NGINX_MODE docker)" == "host" ]] \
|
||||
|| port_in_use "${NGINX_HTTP_PORT:-80}" \
|
||||
|| port_in_use "${NGINX_HTTPS_PORT:-443}"; then
|
||||
echo -e " ${RED}✘${NC} Конфликт: контейнер lendry-id-nginx запущен при занятых портах 80/443 или NGINX_MODE=host"
|
||||
echo " Решение: ./install.sh --fix-all"
|
||||
issues=$((issues + 1))
|
||||
else
|
||||
echo -e " ${GREEN}✔${NC} Docker Nginx: запущен (режим docker)"
|
||||
fi
|
||||
elif [[ "$(env_get NGINX_MODE docker)" == "docker" ]] && compose_uses_proxy_profile; then
|
||||
echo -e " ${YELLOW}!${NC} Docker Nginx не запущен (ожидался в режиме docker)"
|
||||
issues=$((issues + 1))
|
||||
elif [[ "$(env_get NGINX_MODE docker)" == "host" ]]; then
|
||||
if system_nginx_is_active; then
|
||||
echo -e " ${GREEN}✔${NC} Системный Nginx: активен"
|
||||
elif host_nginx_available; then
|
||||
echo -e " ${YELLOW}!${NC} Системный Nginx установлен, но не активен — sudo systemctl start nginx"
|
||||
issues=$((issues + 1))
|
||||
else
|
||||
echo -e " ${RED}✘${NC} NGINX_MODE=host, но системный Nginx не найден"
|
||||
issues=$((issues + 1))
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$(env_get NGINX_MODE docker)" == "host" ]] \
|
||||
&& [[ "$(env_get INSTALL_MODE local)" != "local" ]] \
|
||||
&& [[ -n "$(env_get DOMAIN_API "")" ]]; then
|
||||
local port
|
||||
for port in 3000 3002 3003; do
|
||||
if ! port_in_use "$port"; then
|
||||
echo -e " ${RED}✘${NC} Порт 127.0.0.1:${port} не слушается — host Nginx получит 502"
|
||||
issues=$((issues + 1))
|
||||
fi
|
||||
done
|
||||
check_local_upstream "API /health" "http://127.0.0.1:3000/health" || issues=$((issues + 1))
|
||||
check_local_upstream "Frontend" "http://127.0.0.1:3002" || issues=$((issues + 1))
|
||||
check_local_upstream "Docs" "http://127.0.0.1:3003/docs" || issues=$((issues + 1))
|
||||
|
||||
if has_cmd nginx && [[ -f "${NGINX_ENABLED}/${NGINX_PREFIX}-frontend.conf" ]]; then
|
||||
if run_root nginx -T 2>/dev/null | grep -q 'proxy_pass http://api-gateway:'; then
|
||||
echo -e " ${RED}✘${NC} В конфиге host Nginx указан docker-hostname api-gateway — хост его не резолвит"
|
||||
echo " Решение: ./install.sh --fix-all (перегенерирует proxy_pass на 127.0.0.1)"
|
||||
issues=$((issues + 1))
|
||||
elif run_root nginx -T 2>/dev/null | grep -q 'proxy_pass http://127.0.0.1:3000'; then
|
||||
echo -e " ${GREEN}✔${NC} /idp-api проксируется на 127.0.0.1:3000"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if docker_cmd ps --format '{{.Names}} {{.Status}}' 2>/dev/null | grep -E 'api-gateway.*(Restarting|unhealthy)' >/dev/null 2>&1; then
|
||||
echo -e " ${RED}✘${NC} api-gateway unhealthy или перезапускается — проверьте: docker compose logs api-gateway"
|
||||
issues=$((issues + 1))
|
||||
elif docker_cmd ps --format '{{.Names}} {{.Status}}' 2>/dev/null | grep -q 'lendry-id-api-gateway.*Up'; then
|
||||
echo -e " ${GREEN}✔${NC} api-gateway: контейнер запущен"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
if [[ "$issues" -eq 0 ]]; then
|
||||
ok "Критических проблем не обнаружено"
|
||||
else
|
||||
warn "Обнаружено проблем: ${issues}. Запустите: ./install.sh --fix-all"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
return "$issues"
|
||||
}
|
||||
|
||||
show_upstream_health() {
|
||||
load_env
|
||||
[[ "$(env_get NGINX_MODE docker)" != "host" ]] && return 0
|
||||
@@ -2538,14 +2676,14 @@ show_status() {
|
||||
echo ""
|
||||
if docker_cmd ps -q -f name=lendry-id-nginx 2>/dev/null | grep -q .; then
|
||||
if [[ "$(env_get NGINX_MODE docker)" == "host" ]]; then
|
||||
warn "КОНФЛИКТ: контейнер lendry-id-nginx запущен при NGINX_MODE=host — выполните: ./install.sh --fix-proxy"
|
||||
warn "КОНФЛИКТ: контейнер lendry-id-nginx запущен при NGINX_MODE=host — выполните: ./install.sh --fix-all"
|
||||
else
|
||||
echo " Docker Nginx: запущен (режим docker; curl 127.0.0.1:3002 не нужен)"
|
||||
fi
|
||||
fi
|
||||
if [[ "$(env_get NGINX_MODE docker)" == "host" ]]; then
|
||||
docker_cmd port lendry-id-frontend 3000/tcp 2>/dev/null | sed 's/^/ frontend port: /' || \
|
||||
warn "frontend не публикует 3000/tcp на хост — выполните: ./install.sh --fix-proxy"
|
||||
warn "frontend не публикует 3000/tcp на хост — выполните: ./install.sh --fix-all"
|
||||
fi
|
||||
echo ""
|
||||
show_upstream_health
|
||||
@@ -2689,17 +2827,17 @@ action_fix_host_proxy() {
|
||||
|
||||
log "Исправление прокси (host Nginx + порты 127.0.0.1)..."
|
||||
|
||||
log "Шаг 1/4: остановка Docker Nginx..."
|
||||
stop_docker_nginx
|
||||
log "Шаг 1/5: остановка Docker Nginx и проверка портов..."
|
||||
ensure_docker_nginx_not_conflicting
|
||||
|
||||
log "Шаг 2/4: compose override (LDAP / Nginx)..."
|
||||
log "Шаг 2/5: compose override (LDAP / Nginx)..."
|
||||
write_compose_override
|
||||
|
||||
log "Шаг 3/4: пересоздание api-gateway, frontend, docs, media-ws..."
|
||||
log "Шаг 3/5: пересоздание api-gateway, frontend, docs, media-ws..."
|
||||
compose_build_and_up "${HOST_EDGE_SERVICES[@]}"
|
||||
ensure_host_upstreams
|
||||
|
||||
log "Шаг 4/4: конфиги системного Nginx..."
|
||||
log "Шаг 4/5: конфиги системного Nginx..."
|
||||
refresh_host_nginx_configs
|
||||
|
||||
apply_intranet_selfsigned_runtime
|
||||
@@ -2708,6 +2846,83 @@ action_fix_host_proxy() {
|
||||
compose_build_and_up ldap-auth sso-core
|
||||
|
||||
ok "Прокси исправлен — проверьте: curl -I http://127.0.0.1:3002"
|
||||
diagnose_common_issues || true
|
||||
show_status
|
||||
}
|
||||
|
||||
# Комплексное исправление: 502 на /idp-api, конфликт Docker/host Nginx, порты upstream,
|
||||
# пересборка api-gateway после смены IP контейнера, актуализация конфигов Nginx.
|
||||
action_fix_all_errors() {
|
||||
[[ -f .env ]] || fail "Файл .env не найден — сначала выполните ./install.sh --install"
|
||||
load_env
|
||||
NON_INTERACTIVE=1
|
||||
|
||||
echo ""
|
||||
echo -e "${BOLD}Комплексное исправление ошибок IdP${NC}"
|
||||
echo " (502 Bad Gateway, /idp-api, конфликт Nginx, порты 3000/3002/3003)"
|
||||
echo ""
|
||||
|
||||
log "Шаг 1/6: диагностика..."
|
||||
diagnose_common_issues || true
|
||||
|
||||
log "Шаг 2/6: определение режима Nginx и устранение конфликта портов 80/443..."
|
||||
resolve_nginx_mode_and_ports
|
||||
ensure_docker_nginx_not_conflicting
|
||||
write_compose_override
|
||||
|
||||
log "Шаг 3/6: пересборка api-gateway и sso-core..."
|
||||
compose_build_and_up api-gateway sso-core
|
||||
wait_for_service "sso-core" 120
|
||||
wait_for_service "api-gateway" 90
|
||||
|
||||
log "Шаг 4/6: пересоздание edge-сервисов (frontend, docs, media-ws)..."
|
||||
compose_build_and_up "${HOST_EDGE_SERVICES[@]}"
|
||||
wait_for_service "frontend" 60
|
||||
wait_for_service "docs" 60
|
||||
|
||||
if [[ "$(env_get NGINX_MODE docker)" == "host" ]]; then
|
||||
log "Шаг 5/6: host Nginx — порты 127.0.0.1 и конфиги..."
|
||||
ensure_host_upstreams
|
||||
refresh_host_nginx_configs
|
||||
apply_intranet_selfsigned_runtime
|
||||
compose_build_and_up ldap-auth
|
||||
else
|
||||
log "Шаг 5/6: Docker Nginx — перегенерация конфигов и перезапуск..."
|
||||
local ssl_type
|
||||
ssl_type="$(env_get SSL_TYPE none)"
|
||||
case "$ssl_type" in
|
||||
none) write_nginx_http_only || warn "Не удалось записать HTTP-конфиги Nginx" ;;
|
||||
selfsigned)
|
||||
generate_all_self_signed_certs
|
||||
write_all_nginx_configs "selfsigned" || warn "Не удалось обновить конфиги Nginx"
|
||||
;;
|
||||
custom)
|
||||
install_custom_certificates
|
||||
write_all_nginx_configs "custom" || warn "Не удалось обновить конфиги Nginx"
|
||||
;;
|
||||
letsencrypt)
|
||||
write_all_nginx_configs "letsencrypt" || warn "Не удалось обновить конфиги Nginx"
|
||||
;;
|
||||
esac
|
||||
if compose_uses_proxy_profile; then
|
||||
compose_build_and_up nginx
|
||||
wait_for_service "nginx" 30
|
||||
else
|
||||
warn "Docker Nginx не запущен — порты 80/443 заняты; используется системный Nginx"
|
||||
env_set NGINX_MODE "host"
|
||||
NGINX_MODE="host"
|
||||
refresh_host_nginx_configs
|
||||
fi
|
||||
fi
|
||||
|
||||
log "Шаг 6/6: финальная проверка..."
|
||||
diagnose_common_issues || true
|
||||
|
||||
ok "Исправление завершено"
|
||||
echo ""
|
||||
echo " Проверьте в браузере страницу после авторизации — запросы к /idp-api/* должны отвечать 200."
|
||||
echo " Если ошибки остались: docker compose logs --tail=80 api-gateway"
|
||||
echo ""
|
||||
show_status
|
||||
}
|
||||
|
||||
@@ -2739,11 +2954,12 @@ show_menu() {
|
||||
echo " 6) Удалить конфиги Nginx IdP"
|
||||
echo " 7) Сброс PostgreSQL (если ошибка P1000 / пароль БД)"
|
||||
echo " 8) Очистить Docker (образы/кеш, без пересборки)"
|
||||
echo " 9) Исправить все ошибки (502, /idp-api, Nginx, порты)"
|
||||
echo " 0) Выход"
|
||||
echo ""
|
||||
|
||||
local choice
|
||||
read -r -p "Выберите пункт [0-8]: " choice
|
||||
read -r -p "Выберите пункт [0-9]: " choice
|
||||
|
||||
case "$choice" in
|
||||
1) NON_INTERACTIVE=0; action_full_install ;;
|
||||
@@ -2754,6 +2970,7 @@ show_menu() {
|
||||
6) remove_nginx_configs; ok "Готово" ;;
|
||||
7) action_reset_db; action_restart ;;
|
||||
8) action_docker_prune ;;
|
||||
9) action_fix_all_errors ;;
|
||||
0) exit 0 ;;
|
||||
*) warn "Неверный пункт" ;;
|
||||
esac
|
||||
@@ -2775,6 +2992,7 @@ main() {
|
||||
restart) action_restart ;;
|
||||
docker-prune) action_docker_prune ;;
|
||||
fix-proxy) action_fix_host_proxy ;;
|
||||
fix-all) action_fix_all_errors ;;
|
||||
status) show_status ;;
|
||||
reset-db) action_reset_db ;;
|
||||
remove-nginx) remove_nginx_configs ;;
|
||||
|
||||
Reference in New Issue
Block a user