From 2a488f2ab67ac2c57db77fa53fce8b4854a67992 Mon Sep 17 00:00:00 2001 From: lendry Date: Wed, 1 Jul 2026 19:26:38 +0300 Subject: [PATCH] fix and update --- .env.example | 6 +- install.sh | 214 ++++++++++++++++++++++++--------------------------- 2 files changed, 105 insertions(+), 115 deletions(-) diff --git a/.env.example b/.env.example index dee31c6..6951e96 100644 --- a/.env.example +++ b/.env.example @@ -4,10 +4,10 @@ # Режим: local | intranet | production INSTALL_MODE=local -# Nginx: auto (Windows → Docker) | host (Linux) | docker -NGINX_MODE=auto +# Nginx: docker (контейнер lendry-id-nginx на 80/443) | host (только с --nginx-mode host) +NGINX_MODE=docker -# Порты Nginx-контейнера (если 80/443 заняты системным nginx) +# Порты Nginx-контейнера (если 80/443 заняты другим процессом — install.sh предложит 8080/8443) NGINX_HTTP_PORT=80 NGINX_HTTPS_PORT=443 diff --git a/install.sh b/install.sh index 00d32f7..d86ba27 100644 --- a/install.sh +++ b/install.sh @@ -10,7 +10,7 @@ set -euo pipefail -SCRIPT_VERSION="2.6.2" +SCRIPT_VERSION="2.6.3" ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$ROOT_DIR" @@ -32,7 +32,7 @@ ACTION="" INSTALL_LOCAL=0 INSTALL_INTRANET=0 OFFLINE="${OFFLINE:-0}" -NGINX_MODE="${NGINX_MODE:-auto}" +NGINX_MODE="${NGINX_MODE:-docker}" SKIP_DOCKER_PRUNE="${SKIP_DOCKER_PRUNE:-0}" DOCKER_PRUNE_AGGRESSIVE="${DOCKER_PRUNE_AGGRESSIVE:-0}" # Принудительный Docker Nginx (контейнер lendry-id-nginx) — включается в --fix-all @@ -76,7 +76,8 @@ ${BOLD}Lendry ID v${SCRIPT_VERSION}${NC} — установка и управл ./install.sh --renew-ssl Обновить сертификаты (Let's Encrypt / custom / selfsigned) ./install.sh --restart Перезапуск контейнеров ./install.sh --migrate-rebuild Миграции Prisma + пересборка стека (после git pull) - ./install.sh --fix-host-nginx Host Nginx: остановить Docker Nginx, поднять system nginx + ./install.sh --fix-host-nginx Устарело: восстановить Docker Nginx (lendry-id-nginx) + ./install.sh --fix-docker-nginx Остановить system nginx, поднять lendry-id-nginx ./install.sh --docker-prune Только очистка Docker (без пересборки) ./install.sh --fix-proxy Исправить 502: host Nginx + порты 3000/3002/3003 ./install.sh --fix-all Комплексное исправление: 502, прокси, порты, Nginx @@ -160,7 +161,8 @@ parse_args() { --renew-ssl) ACTION="renew-ssl"; shift ;; --restart) ACTION="restart"; shift ;; --migrate-rebuild) ACTION="migrate-rebuild"; shift ;; - --fix-host-nginx) ACTION="fix-host-nginx"; shift ;; + --fix-host-nginx) ACTION="fix-docker-nginx"; shift ;; + --fix-docker-nginx) ACTION="fix-docker-nginx"; shift ;; --docker-prune) ACTION="docker-prune"; shift ;; --skip-docker-prune) SKIP_DOCKER_PRUNE=1; shift ;; --docker-prune-aggressive) DOCKER_PRUNE_AGGRESSIVE=1; shift ;; @@ -175,7 +177,7 @@ parse_args() { --cert-dir) CLI_CERT_DIR="${2:-}"; shift 2 ;; --cert-fullchain) CLI_CERT_FULLCHAIN="${2:-}"; shift 2 ;; --cert-key) CLI_CERT_KEY="${2:-}"; shift 2 ;; - --nginx-mode) NGINX_MODE="${2:-auto}"; NGINX_MODE_CLI="${2:-auto}"; shift 2 ;; + --nginx-mode) NGINX_MODE="${2:-docker}"; NGINX_MODE_CLI="${2:-docker}"; shift 2 ;; --nginx-http-port) CLI_NGINX_HTTP_PORT="${2:-}"; shift 2 ;; --nginx-https-port) CLI_NGINX_HTTPS_PORT="${2:-}"; shift 2 ;; --api-domain) CLI_DOMAIN_API="${2:-}"; shift 2 ;; @@ -234,19 +236,21 @@ preflight_checks() { detect_nginx_mode() { load_env - if [[ -n "$(env_get NGINX_MODE "")" && "$(env_get NGINX_MODE auto)" != "auto" ]]; then - NGINX_MODE="$(env_get NGINX_MODE auto)" + if [[ -n "$(env_get NGINX_MODE "")" && "$(env_get NGINX_MODE docker)" != "auto" ]]; then + NGINX_MODE="$(env_get NGINX_MODE docker)" fi if [[ "$NGINX_MODE" == "auto" ]]; then - if [[ "$(uname -s)" == "Linux" ]] && { [[ -d /etc/nginx ]] || has_cmd nginx; }; then - NGINX_MODE="host" - else - NGINX_MODE="docker" - fi + NGINX_MODE="docker" fi - log "Режим Nginx: ${NGINX_MODE} (host=системный, docker=контейнер)" + # Host-режим устарел: без явного --nginx-mode host всегда Docker Nginx + if [[ "$NGINX_MODE" == "host" && "$NGINX_MODE_CLI" != "host" ]]; then + warn "NGINX_MODE=host в .env устарел — используется Docker Nginx (lendry-id-nginx)" + NGINX_MODE="docker" + fi + + log "Режим Nginx: ${NGINX_MODE} (docker=контейнер lendry-id-nginx, host=только с --nginx-mode host)" } port_in_use() { @@ -292,6 +296,28 @@ disable_host_nginx_lendry() { fi } +# Освобождает 80/443 для lendry-id-nginx: отключает IdP в system nginx и останавливает его. +prepare_docker_nginx_ports() { + load_env + disable_host_nginx_lendry + + NGINX_HTTP_PORT="${NGINX_HTTP_PORT:-$(env_get NGINX_HTTP_PORT 80)}" + NGINX_HTTPS_PORT="${NGINX_HTTPS_PORT:-$(env_get NGINX_HTTPS_PORT 443)}" + [[ -n "$CLI_NGINX_HTTP_PORT" ]] && NGINX_HTTP_PORT="$CLI_NGINX_HTTP_PORT" + [[ -n "$CLI_NGINX_HTTPS_PORT" ]] && NGINX_HTTPS_PORT="$CLI_NGINX_HTTPS_PORT" + + if system_nginx_is_active \ + || { port_in_use "$NGINX_HTTP_PORT" && host_nginx_available; } \ + || { port_in_use "$NGINX_HTTPS_PORT" && host_nginx_available; }; then + log "Остановка системного Nginx (освобождение портов ${NGINX_HTTP_PORT}/${NGINX_HTTPS_PORT} для lendry-id-nginx)..." + run_root systemctl stop nginx 2>/dev/null || run_root service nginx stop 2>/dev/null || true + sleep 2 + fi + + env_set NGINX_HTTP_PORT "$NGINX_HTTP_PORT" + env_set NGINX_HTTPS_PORT "$NGINX_HTTPS_PORT" +} + # --fix-all / --install: всегда Docker Nginx (lendry-id-nginx), не системный на 80/443 ensure_docker_nginx_mode_for_fix_all() { load_env @@ -301,26 +327,10 @@ ensure_docker_nginx_mode_for_fix_all() { log "Переключение на Docker Nginx (контейнер lendry-id-nginx)..." - disable_host_nginx_lendry - - NGINX_HTTP_PORT="${NGINX_HTTP_PORT:-$(env_get NGINX_HTTP_PORT 80)}" - NGINX_HTTPS_PORT="${NGINX_HTTPS_PORT:-$(env_get NGINX_HTTPS_PORT 443)}" - [[ -n "$CLI_NGINX_HTTP_PORT" ]] && NGINX_HTTP_PORT="$CLI_NGINX_HTTP_PORT" - [[ -n "$CLI_NGINX_HTTPS_PORT" ]] && NGINX_HTTPS_PORT="$CLI_NGINX_HTTPS_PORT" - - if system_nginx_is_active \ - || port_in_use "$NGINX_HTTP_PORT" \ - || port_in_use "$NGINX_HTTPS_PORT"; then - log "Остановка системного Nginx (освобождение портов ${NGINX_HTTP_PORT}/${NGINX_HTTPS_PORT})..." - run_root systemctl stop nginx 2>/dev/null || run_root service nginx stop 2>/dev/null || true - sleep 2 - fi + prepare_docker_nginx_ports docker_cmd rm -f lendry-id-nginx 2>/dev/null || true - env_set NGINX_HTTP_PORT "$NGINX_HTTP_PORT" - env_set NGINX_HTTPS_PORT "$NGINX_HTTPS_PORT" - if port_in_use "$NGINX_HTTP_PORT" || port_in_use "$NGINX_HTTPS_PORT"; then warn "Порты ${NGINX_HTTP_PORT}/${NGINX_HTTPS_PORT} всё ещё заняты после остановки system nginx" if has_cmd ss; then @@ -344,41 +354,20 @@ ensure_docker_nginx_mode_for_install() { ensure_docker_nginx_mode_for_fix_all } -# Не даём контейнерному nginx занять 80/443, если их уже держит системный nginx -# или явно выбран NGINX_MODE=host (типичная причина «address already in use»). +# Docker Nginx на 80/443: не переключаемся на system nginx при занятых портах — освобождаем их. ensure_docker_nginx_not_conflicting() { load_env - if [[ "${FORCE_DOCKER_NGINX:-0}" -eq 1 ]]; then + if [[ "${FORCE_DOCKER_NGINX:-0}" -eq 1 ]] || [[ "$(env_get NGINX_MODE docker)" == "docker" ]]; then NGINX_MODE="docker" + env_set NGINX_MODE "docker" + prepare_docker_nginx_ports return 0 fi - 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 + if [[ "$(env_get NGINX_MODE docker)" == "host" ]]; then stop_docker_nginx - if [[ "$(env_get NGINX_MODE docker)" == "host" ]]; then - ensure_host_nginx_stack || true - fi + ensure_host_nginx_stack || true fi } @@ -432,14 +421,26 @@ ensure_host_nginx_stack() { } action_fix_host_nginx() { + warn "--fix-host-nginx устарел — используется Docker Nginx (lendry-id-nginx)" + action_fix_docker_nginx +} + +action_fix_docker_nginx() { [[ -f .env ]] || fail "Файл .env не найден" load_env + NON_INTERACTIVE=1 + + log "Восстановление Docker Nginx (lendry-id-nginx)..." + ensure_docker_nginx_mode_for_fix_all prepare_compose_stack - ensure_host_nginx_stack || fail "Не удалось восстановить системный Nginx" - recreate_host_port_services || true - ensure_host_upstreams || true - show_upstream_health - ok "Host Nginx восстановлен — проверьте сайт в браузере" + ensure_nginx_after_stack_rebuild || fail "Не удалось запустить lendry-id-nginx" + sync_nginx_after_api_gateway_restart || true + sync_nginx_after_edge_restart || true + reload_docker_nginx || true + post_deploy_proxy_verify 0 || warn "Проверка прокси не прошла — выполните: ./install.sh --fix-all" + diagnose_common_issues || true + ok "Docker Nginx (lendry-id-nginx) восстановлен — проверьте сайт в браузере" + show_status } reload_docker_nginx() { @@ -670,14 +671,10 @@ resolve_nginx_mode_and_ports() { detect_nginx_mode - if system_nginx_is_active || lendry_host_nginx_configured; then - if [[ "$NGINX_MODE" == "docker" ]]; then - warn "На сервере активен системный Nginx — переключаем NGINX_MODE на host" - warn "Docker Nginx (lendry-id-nginx) не совместим с системным Nginx на 443" - NGINX_MODE="host" - env_set NGINX_MODE "host" - fi + if [[ "$NGINX_MODE" == "docker" ]]; then + prepare_docker_nginx_ports fi + if [[ -n "$CLI_NGINX_HTTP_PORT" ]]; then NGINX_HTTP_PORT="$CLI_NGINX_HTTP_PORT" env_set NGINX_HTTP_PORT "$NGINX_HTTP_PORT" @@ -692,12 +689,8 @@ 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 || 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" - elif [[ "$NGINX_HTTP_PORT" == "80" && "$NON_INTERACTIVE" -eq 1 ]]; then - warn "Порт 80 занят — Docker Nginx будет на 8080/8443" + if [[ "$NGINX_HTTP_PORT" == "80" && "$NON_INTERACTIVE" -eq 1 ]]; then + warn "Порт 80/443 занят — Docker Nginx будет на 8080/8443" NGINX_HTTP_PORT="8080" NGINX_HTTPS_PORT="8443" env_set NGINX_HTTP_PORT "8080" @@ -705,16 +698,15 @@ resolve_nginx_mode_and_ports() { elif [[ "$NGINX_HTTP_PORT" == "80" ]]; then echo "" warn "Порт 80 или 443 уже занят на этом сервере." - echo " 1) Системный Nginx (рекомендуется, если nginx уже установлен)" + echo " 1) Остановить системный Nginx и использовать Docker на 80/443 (рекомендуется)" echo " 2) Docker Nginx на портах 8080 / 8443" - echo " 3) Отмена — освободите 80/443 и повторите" + echo " 3) Отмена — освободите 80/443 вручную и повторите" local port_choice read -r -p "Выберите [1-3] [1]: " port_choice port_choice="${port_choice:-1}" case "$port_choice" in 1) - NGINX_MODE="host" - env_set NGINX_MODE "host" + prepare_docker_nginx_ports ;; 2) NGINX_HTTP_PORT="8080" @@ -723,7 +715,7 @@ resolve_nginx_mode_and_ports() { env_set NGINX_HTTPS_PORT "8443" ;; *) - fail "Освободите порт 80: sudo systemctl stop nginx или укажите --nginx-mode host" + fail "Освободите порт 80: sudo systemctl stop nginx или укажите --nginx-http-port 8080" ;; esac else @@ -1127,7 +1119,7 @@ load_env() { # shellcheck disable=SC1091 set -a && source .env && set +a fi - NGINX_MODE="${NGINX_MODE:-auto}" + NGINX_MODE="${NGINX_MODE:-docker}" } env_get() { @@ -1610,6 +1602,11 @@ fi' action_migrate_rebuild() { [[ -f .env ]] || fail "Файл .env не найден — сначала выполните ./install.sh --install" load_env + if [[ "$(env_get INSTALL_MODE local)" != "local" ]] && [[ -n "$(env_get DOMAIN_API "")" ]] && [[ "$NGINX_MODE_CLI" != "host" ]]; then + NGINX_MODE="docker" + env_set NGINX_MODE "docker" + prepare_docker_nginx_ports + fi prepare_compose_stack echo "" @@ -1638,25 +1635,16 @@ action_migrate_rebuild() { wait_for_service docs 60 log "Шаг 4/4: Nginx, прокси и проверка..." - ensure_nginx_after_stack_rebuild || warn "Nginx не восстановлен — выполните: ./install.sh --fix-host-nginx" - if [[ "$(env_get NGINX_MODE docker)" == "host" ]]; then - show_upstream_health - check_https_api_with_origin || warn "HTTPS-проверка не прошла — выполните: ./install.sh --fix-host-nginx" - else - post_deploy_proxy_verify 0 || true - fi + 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 - if [[ "$(env_get NGINX_MODE docker)" == "host" ]]; then - if docker_nginx_container_running; then - fail "Конфликт: lendry-id-nginx запущен при NGINX_MODE=host. Выполните: ./install.sh --fix-host-nginx" - fi - if ! system_nginx_is_active; then - fail "Системный Nginx не запущен. Выполните: ./install.sh --fix-host-nginx" - fi - elif compose_uses_proxy_profile && ! docker_nginx_container_running; then + if compose_uses_proxy_profile && ! docker_nginx_container_running; then fail "Сайт недоступен: lendry-id-nginx не запущен. Выполните: ./install.sh --fix-all" fi + if docker_nginx_container_running && system_nginx_is_active; then + warn "Конфликт: системный Nginx и lendry-id-nginx одновременно — выполните: ./install.sh --fix-docker-nginx" + fi ok "Миграция и пересборка завершены" echo "" @@ -1669,7 +1657,7 @@ persist_domain_env() { write_env_secrets_if_missing env_set INSTALL_MODE "${INSTALL_MODE:-local}" - env_set NGINX_MODE "${NGINX_MODE:-auto}" + env_set NGINX_MODE "${NGINX_MODE:-docker}" env_set SSL_TYPE "${SSL_TYPE:-none}" env_set DOMAIN_API "${DOMAIN_API:-}" env_set DOMAIN_FRONTEND "${DOMAIN_FRONTEND:-}" @@ -2943,14 +2931,16 @@ remove_nginx_configs() { ensure_nginx_mode_for_config_write() { load_env if [[ "${FORCE_DOCKER_NGINX:-0}" -eq 1 ]] \ - || [[ "$(env_get NGINX_MODE auto)" == "docker" ]] \ + || [[ "$(env_get NGINX_MODE docker)" == "docker" ]] \ || docker_nginx_container_running; then NGINX_MODE="docker" env_set NGINX_MODE "docker" - elif [[ -n "$(env_get NGINX_MODE "")" && "$(env_get NGINX_MODE auto)" != "auto" ]]; then - NGINX_MODE="$(env_get NGINX_MODE auto)" + elif [[ "$NGINX_MODE_CLI" == "host" ]] && [[ "$(env_get NGINX_MODE docker)" == "host" ]]; then + NGINX_MODE="host" else detect_nginx_mode + NGINX_MODE="docker" + env_set NGINX_MODE "docker" fi log "Запись конфигов Nginx: mode=${NGINX_MODE}, каталог=${LOCAL_CONF_DIR}" } @@ -3674,7 +3664,7 @@ print_summary() { echo -e "${GREEN} Lendry ID — развёртывание завершено${NC}" echo -e "${GREEN}══════════════════════════════════════════════════════════════${NC}" echo "" - echo -e " ${BOLD}Режим:${NC} ${INSTALL_MODE:-local} | SSL: ${SSL_TYPE:-none} | Nginx: ${NGINX_MODE:-auto}" + echo -e " ${BOLD}Режим:${NC} ${INSTALL_MODE:-local} | SSL: ${SSL_TYPE:-none} | Nginx: ${NGINX_MODE:-docker}" echo -e " ${BOLD}API / Swagger:${NC} ${PUBLIC_API_URL}/docs" echo -e " ${BOLD}Frontend:${NC} ${PUBLIC_FRONTEND_URL}" echo -e " ${BOLD}Документация:${NC} ${PUBLIC_DOCS_URL}/docs" @@ -3836,8 +3826,8 @@ diagnose_common_issues() { echo " Решение: sudo systemctl stop nginx && ./install.sh --fix-all" issues=$((issues + 1)) elif [[ "$(env_get NGINX_MODE docker)" == "host" ]]; then - echo -e " ${RED}✘${NC} Конфликт: NGINX_MODE=host, но запущен lendry-id-nginx" - echo " Решение: ./install.sh --fix-host-nginx" + echo -e " ${RED}✘${NC} NGINX_MODE=host устарел — используйте Docker Nginx" + echo " Решение: ./install.sh --fix-docker-nginx" issues=$((issues + 1)) elif [[ "$(env_get NGINX_MODE docker)" == "docker" ]] \ && ! docker_nginx_container_running \ @@ -4004,7 +3994,7 @@ show_status() { echo " SSL_CERT_DIR: $(env_get SSL_CERT_DIR -)" echo " SSL установлен: ${CUSTOM_CERT_TARGET_DIR}/" fi - echo " NGINX_MODE: $(env_get NGINX_MODE auto)" + echo " NGINX_MODE: $(env_get NGINX_MODE docker)" echo " USE_NGINX_SSL: $(env_get USE_NGINX_SSL false)" echo " DOMAIN_API: $(env_get DOMAIN_API -)" echo " DOMAIN_FRONTEND: $(env_get DOMAIN_FRONTEND -)" @@ -4020,16 +4010,16 @@ 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-host-nginx" + warn "NGINX_MODE=host устарел при запущенном lendry-id-nginx — выполните: ./install.sh --fix-docker-nginx" else - echo " Docker Nginx: запущен (режим docker; curl 127.0.0.1:3002 не нужен)" + echo " Docker Nginx: запущен (lendry-id-nginx)" fi + elif [[ "$(env_get NGINX_MODE docker)" == "docker" ]] \ + && [[ "$(env_get INSTALL_MODE local)" != "local" ]] \ + && [[ -n "$(env_get DOMAIN_API "")" ]]; then + warn "Docker Nginx: не запущен — выполните: ./install.sh --fix-docker-nginx" elif [[ "$(env_get NGINX_MODE docker)" == "host" ]]; then - if system_nginx_is_active; then - echo " Host Nginx: активен (systemd)" - else - warn "Host Nginx: не запущен — выполните: ./install.sh --fix-host-nginx" - fi + warn "NGINX_MODE=host устарел — выполните: ./install.sh --fix-docker-nginx" fi if [[ "$(env_get NGINX_MODE docker)" == "host" ]]; then docker_cmd port lendry-id-frontend 3000/tcp 2>/dev/null | sed 's/^/ frontend port: /' || \ @@ -4442,7 +4432,7 @@ main() { renew-ssl) action_renew_ssl ;; restart) action_restart ;; migrate-rebuild) action_migrate_rebuild ;; - fix-host-nginx) action_fix_host_nginx ;; + fix-host-nginx|fix-docker-nginx) action_fix_docker_nginx ;; docker-prune) action_docker_prune ;; fix-proxy) action_fix_host_proxy ;; fix-all) action_fix_all_errors ;;