fix idp on started

This commit is contained in:
lendry
2026-06-24 16:21:29 +03:00
parent 34c1d8446a
commit 36f30039ad
3 changed files with 302 additions and 15 deletions

View File

@@ -7,6 +7,10 @@ INSTALL_MODE=local
# Nginx: auto (Windows → Docker) | host (Linux) | docker # Nginx: auto (Windows → Docker) | host (Linux) | docker
NGINX_MODE=auto NGINX_MODE=auto
# Порты Nginx-контейнера (если 80/443 заняты системным nginx)
NGINX_HTTP_PORT=80
NGINX_HTTPS_PORT=443
# SSL: none (HTTP) | selfsigned (HTTPS локально) | letsencrypt (интернет) # SSL: none (HTTP) | selfsigned (HTTPS локально) | letsencrypt (интернет)
SSL_TYPE=none SSL_TYPE=none

View File

@@ -253,8 +253,8 @@ services:
container_name: lendry-id-nginx container_name: lendry-id-nginx
restart: unless-stopped restart: unless-stopped
ports: ports:
- "80:80" - "${NGINX_HTTP_PORT:-80}:80"
- "443:443" - "${NGINX_HTTPS_PORT:-443}:443"
volumes: volumes:
- ./nginx/conf.d:/etc/nginx/conf.d:ro - ./nginx/conf.d:/etc/nginx/conf.d:ro
- ./nginx/certs:/etc/nginx/certs:ro - ./nginx/certs:/etc/nginx/certs:ro

View File

@@ -10,7 +10,7 @@
set -euo pipefail set -euo pipefail
SCRIPT_VERSION="2.1.0" SCRIPT_VERSION="2.2.0"
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$ROOT_DIR" cd "$ROOT_DIR"
@@ -40,6 +40,8 @@ CLI_DOMAIN_MINIO=""
CLI_DOMAIN_MINIO_CONSOLE="" CLI_DOMAIN_MINIO_CONSOLE=""
CLI_EMAIL="" CLI_EMAIL=""
CLI_SSL_TYPE="" CLI_SSL_TYPE=""
CLI_NGINX_HTTP_PORT=""
CLI_NGINX_HTTPS_PORT=""
RED='\033[0;31m' RED='\033[0;31m'
GREEN='\033[0;32m' GREEN='\033[0;32m'
@@ -62,6 +64,7 @@ ${BOLD}Lendry ID v${SCRIPT_VERSION}${NC} — установка и управл
./install.sh --configure-domains Изменить домены / Nginx / SSL ./install.sh --configure-domains Изменить домены / Nginx / SSL
./install.sh --renew-ssl Обновить сертификаты Let's Encrypt ./install.sh --renew-ssl Обновить сертификаты Let's Encrypt
./install.sh --restart Перезапуск контейнеров ./install.sh --restart Перезапуск контейнеров
./install.sh --fix-proxy Исправить 502: host Nginx + порты 3000/3002/3003
./install.sh --status Статус сервисов ./install.sh --status Статус сервисов
./install.sh --reset-db Сброс PostgreSQL (новый пароль из .env, данные удалятся) ./install.sh --reset-db Сброс PostgreSQL (новый пароль из .env, данные удалятся)
./install.sh --remove-nginx Удалить конфиги Nginx IdP ./install.sh --remove-nginx Удалить конфиги Nginx IdP
@@ -69,7 +72,8 @@ ${BOLD}Lendry ID v${SCRIPT_VERSION}${NC} — установка и управл
${BOLD}Режим локальной сети (без интернета / AD-домены .local .lpr):${NC} ${BOLD}Режим локальной сети (без интернета / AD-домены .local .lpr):${NC}
--intranet Локальная сеть: HTTP или самоподписанный HTTPS --intranet Локальная сеть: HTTP или самоподписанный HTTPS
--ssl TYPE none | selfsigned | letsencrypt (по умолчанию в --intranet: none) --ssl TYPE none | selfsigned | letsencrypt (по умолчанию в --intranet: none)
--nginx-mode MODE auto | host | docker (Windows → docker) --nginx-http-port PORT HTTP-порт Nginx (если 80 занят, например 8080)
--nginx-https-port PORT HTTPS-порт Nginx (если 443 занят, например 8443)
--offline Не скачивать Docker из интернета (только если уже установлен) --offline Не скачивать Docker из интернета (только если уже установлен)
${BOLD}Домены (можно указывать отдельно):${NC} ${BOLD}Домены (можно указывать отдельно):${NC}
@@ -118,6 +122,7 @@ parse_args() {
--configure-domains) ACTION="configure-domains"; shift ;; --configure-domains) ACTION="configure-domains"; shift ;;
--renew-ssl) ACTION="renew-ssl"; shift ;; --renew-ssl) ACTION="renew-ssl"; shift ;;
--restart) ACTION="restart"; shift ;; --restart) ACTION="restart"; shift ;;
--fix-proxy) ACTION="fix-proxy"; shift ;;
--status) ACTION="status"; shift ;; --status) ACTION="status"; shift ;;
--reset-db) ACTION="reset-db"; shift ;; --reset-db) ACTION="reset-db"; shift ;;
--local) INSTALL_LOCAL=1; shift ;; --local) INSTALL_LOCAL=1; shift ;;
@@ -125,6 +130,8 @@ parse_args() {
--offline) OFFLINE=1; shift ;; --offline) OFFLINE=1; shift ;;
--ssl) CLI_SSL_TYPE="${2:-}"; shift 2 ;; --ssl) CLI_SSL_TYPE="${2:-}"; shift 2 ;;
--nginx-mode) NGINX_MODE="${2:-auto}"; shift 2 ;; --nginx-mode) NGINX_MODE="${2:-auto}"; 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 ;; --api-domain) CLI_DOMAIN_API="${2:-}"; shift 2 ;;
--frontend-domain) CLI_DOMAIN_FRONTEND="${2:-}"; shift 2 ;; --frontend-domain) CLI_DOMAIN_FRONTEND="${2:-}"; shift 2 ;;
--docs-domain) CLI_DOMAIN_DOCS="${2:-}"; shift 2 ;; --docs-domain) CLI_DOMAIN_DOCS="${2:-}"; shift 2 ;;
@@ -196,6 +203,128 @@ detect_nginx_mode() {
log "Режим Nginx: ${NGINX_MODE} (host=системный, docker=контейнер)" log "Режим Nginx: ${NGINX_MODE} (host=системный, docker=контейнер)"
} }
port_in_use() {
local port="$1"
if has_cmd ss; then
ss -tln 2>/dev/null | grep -qE ":${port}[[:space:]]"
elif has_cmd netstat; then
netstat -tln 2>/dev/null | grep -qE ":${port}[[:space:]]"
else
return 1
fi
}
host_nginx_available() {
[[ -d /etc/nginx ]] || has_cmd nginx
}
system_nginx_is_active() {
has_cmd systemctl && systemctl is-active --quiet nginx 2>/dev/null
}
lendry_host_nginx_configured() {
[[ -f "${NGINX_ENABLED}/${NGINX_PREFIX}-frontend.conf" ]] \
|| [[ -L "${NGINX_ENABLED}/${NGINX_PREFIX}-frontend.conf" ]]
}
stop_docker_nginx() {
if docker_cmd ps -q -f name=lendry-id-nginx 2>/dev/null | grep -q .; then
log "Останавливаем контейнер lendry-id-nginx (используется системный Nginx)..."
docker_cmd compose --env-file .env --profile proxy stop nginx 2>/dev/null || true
docker_cmd rm -f lendry-id-nginx 2>/dev/null || true
ok "Docker Nginx остановлен"
fi
}
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
}
resolve_nginx_mode_and_ports() {
load_env
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
fi
if [[ -n "$CLI_NGINX_HTTP_PORT" ]]; then
NGINX_HTTP_PORT="$CLI_NGINX_HTTP_PORT"
env_set NGINX_HTTP_PORT "$NGINX_HTTP_PORT"
fi
if [[ -n "$CLI_NGINX_HTTPS_PORT" ]]; then
NGINX_HTTPS_PORT="$CLI_NGINX_HTTPS_PORT"
env_set NGINX_HTTPS_PORT "$NGINX_HTTPS_PORT"
fi
NGINX_HTTP_PORT="${NGINX_HTTP_PORT:-$(env_get NGINX_HTTP_PORT 80)}"
NGINX_HTTPS_PORT="${NGINX_HTTPS_PORT:-$(env_get NGINX_HTTPS_PORT 443)}"
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
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"
NGINX_HTTP_PORT="8080"
NGINX_HTTPS_PORT="8443"
env_set NGINX_HTTP_PORT "8080"
env_set NGINX_HTTPS_PORT "8443"
elif [[ "$NGINX_HTTP_PORT" == "80" ]]; then
echo ""
warn "Порт 80 или 443 уже занят на этом сервере."
echo " 1) Системный Nginx (рекомендуется, если nginx уже установлен)"
echo " 2) Docker Nginx на портах 8080 / 8443"
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"
;;
2)
NGINX_HTTP_PORT="8080"
NGINX_HTTPS_PORT="8443"
env_set NGINX_HTTP_PORT "8080"
env_set NGINX_HTTPS_PORT "8443"
;;
*)
fail "Освободите порт 80: sudo systemctl stop nginx или укажите --nginx-mode host"
;;
esac
else
fail "Порт ${NGINX_HTTP_PORT} или ${NGINX_HTTPS_PORT} занят. Освободите его или укажите другие: --nginx-http-port 8080"
fi
fi
fi
env_set NGINX_MODE "$NGINX_MODE"
env_set NGINX_HTTP_PORT "${NGINX_HTTP_PORT:-80}"
env_set NGINX_HTTPS_PORT "${NGINX_HTTPS_PORT:-443}"
log "Nginx: mode=${NGINX_MODE}, HTTP=${NGINX_HTTP_PORT}, HTTPS=${NGINX_HTTPS_PORT}"
}
compose_uses_proxy_profile() {
load_env
[[ -n "$(env_get DOMAIN_API "")" ]] || return 1
[[ "$(env_get INSTALL_MODE local)" == "local" ]] && return 1
[[ "$(env_get NGINX_MODE docker)" == "docker" ]] || return 1
return 0
}
install_packages_apt() { install_packages_apt() {
run_root apt-get update -qq run_root apt-get update -qq
run_root apt-get install -y -qq ca-certificates curl git openssl gnupg lsb-release jq run_root apt-get install -y -qq ca-certificates curl git openssl gnupg lsb-release jq
@@ -797,8 +926,9 @@ persist_domain_env() {
} }
write_compose_override() { write_compose_override() {
resolve_nginx_mode_and_ports
load_env load_env
local mode="${NGINX_MODE:-$(env_get NGINX_MODE auto)}" local mode="${NGINX_MODE:-$(env_get NGINX_MODE host)}"
local has_domains local has_domains
has_domains="$(env_get DOMAIN_API "")" has_domains="$(env_get DOMAIN_API "")"
@@ -823,6 +953,14 @@ write_compose_override() {
fi fi
if [[ "$mode" == "docker" ]]; then if [[ "$mode" == "docker" ]]; then
local http_port https_port nginx_ports
http_port="$(env_get NGINX_HTTP_PORT 80)"
https_port="$(env_get NGINX_HTTPS_PORT 443)"
nginx_ports="
nginx:
ports: !reset
- \"${http_port}:80\"
- \"${https_port}:443\""
cat >"$COMPOSE_OVERRIDE" <<EOF cat >"$COMPOSE_OVERRIDE" <<EOF
services: services:
api-gateway: api-gateway:
@@ -833,7 +971,7 @@ services:
ports: !reset [] ports: !reset []
media-ws: media-ws:
ports: !reset [] ports: !reset []
${minio_block} ${minio_block}${nginx_ports}
EOF EOF
else else
cat >"$COMPOSE_OVERRIDE" <<EOF cat >"$COMPOSE_OVERRIDE" <<EOF
@@ -855,6 +993,68 @@ EOF
fi fi
} }
HOST_EDGE_SERVICES=(api-gateway frontend docs media-ws)
recreate_host_port_services() {
load_env
[[ "$(env_get NGINX_MODE docker)" == "host" ]] || return 0
[[ -n "$(env_get DOMAIN_API "")" ]] || return 0
[[ "$(env_get INSTALL_MODE local)" == "local" ]] && return 0
log "Пересоздание сервисов с пробросом портов на 127.0.0.1..."
local compose_cmd=(compose --env-file .env)
if compose_uses_proxy_profile; then
compose_cmd+=(--profile proxy)
fi
docker_cmd "${compose_cmd[@]}" up -d --force-recreate "${HOST_EDGE_SERVICES[@]}"
}
ensure_host_upstreams() {
load_env
[[ "$(env_get NGINX_MODE docker)" == "host" ]] || return 0
[[ -n "$(env_get DOMAIN_API "")" ]] || return 0
[[ "$(env_get INSTALL_MODE local)" == "local" ]] && return 0
local missing=0
for spec in "3000:API" "3002:Frontend" "3003:Docs"; do
local port="${spec%%:*}"
if ! port_in_use "$port"; then
warn "Порт ${port} (${spec#*:}) не слушается на хосте"
missing=1
fi
done
if [[ "$missing" -eq 1 ]]; then
warn "Проброс портов не применён — пересоздаём edge-сервисы (NGINX_MODE=host)"
recreate_host_port_services
local attempt=0
while [[ $attempt -lt 12 ]]; do
missing=0
for spec in "3000:API" "3002:Frontend" "3003:Docs"; do
local port="${spec%%:*}"
if ! port_in_use "$port"; then
missing=1
fi
done
[[ "$missing" -eq 0 ]] && break
attempt=$((attempt + 1))
sleep 5
done
for spec in "3000:API" "3002:Frontend" "3003:Docs"; do
local port="${spec%%:*}"
if ! port_in_use "$port"; then
echo ""
warn "Диагностика:"
docker_cmd ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}' 2>/dev/null | sed 's/^/ /' || true
docker_cmd port lendry-id-frontend 2>/dev/null | sed 's/^/ frontend: /' || echo " frontend: порты не опубликованы"
echo ""
fail "Порт ${port} недоступен. Проверьте: grep NGINX_MODE .env && cat docker-compose.override.yml && docker compose logs frontend"
fi
done
ok "Порты 3000/3002/3003 доступны на localhost"
fi
}
nginx_upstream() { nginx_upstream() {
case "$1" in case "$1" in
api) api)
@@ -1382,8 +1582,11 @@ setup_nginx_proxy() {
[[ -n "${DOMAIN_API:-}" ]] || return 0 [[ -n "${DOMAIN_API:-}" ]] || return 0
[[ "$INSTALL_LOCAL" -eq 1 ]] && return 0 [[ "$INSTALL_LOCAL" -eq 1 ]] && return 0
detect_nginx_mode resolve_nginx_mode_and_ports
env_set NGINX_MODE "$NGINX_MODE" write_compose_override
if [[ "$(env_get NGINX_MODE docker)" == "host" ]]; then
stop_docker_nginx
fi
install_nginx_certbot install_nginx_certbot
local ssl_type local ssl_type
@@ -1441,23 +1644,24 @@ deploy_stack() {
export DOCKER_BUILDKIT=1 export DOCKER_BUILDKIT=1
export COMPOSE_DOCKER_CLI_BUILD=1 export COMPOSE_DOCKER_CLI_BUILD=1
write_compose_override prepare_compose_stack
load_env
verify_postgres_auth verify_postgres_auth
local compose_cmd=(compose --env-file .env) local compose_cmd=(compose --env-file .env)
if [[ -n "$(env_get DOMAIN_API "")" && "$(env_get INSTALL_MODE local)" != "local" ]]; then if compose_uses_proxy_profile; then
compose_cmd+=(--profile proxy) compose_cmd+=(--profile proxy)
fi fi
log "Сборка и запуск контейнеров (1020 минут при первом запуске)..." log "Сборка и запуск контейнеров (1020 минут при первом запуске)..."
docker_cmd "${compose_cmd[@]}" up -d --build docker_cmd "${compose_cmd[@]}" up -d --build
recreate_host_port_services
ensure_host_upstreams
wait_for_service "sso-core" 120 wait_for_service "sso-core" 120
wait_for_service "api-gateway" 90 wait_for_service "api-gateway" 90
wait_for_service "frontend" 60 wait_for_service "frontend" 60
wait_for_service "docs" 60 wait_for_service "docs" 60
if [[ " ${compose_cmd[*]} " == *" proxy "* ]]; then if compose_uses_proxy_profile; then
wait_for_service "nginx" 30 wait_for_service "nginx" 30
fi fi
} }
@@ -1517,6 +1721,43 @@ print_summary() {
fi fi
} }
refresh_host_nginx_configs() {
load_env
[[ "$(env_get NGINX_MODE docker)" == "host" ]] || return 0
[[ -n "$(env_get DOMAIN_API "")" ]] || return 0
[[ "$(env_get INSTALL_MODE local)" == "local" ]] && return 0
local ssl_type
ssl_type="$(env_get SSL_TYPE none)"
case "$ssl_type" in
none) write_nginx_http_only ;;
selfsigned) write_all_nginx_configs "selfsigned" ;;
letsencrypt) write_all_nginx_configs "letsencrypt" ;;
esac
}
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}"
else
echo -e " ${RED}${NC} ${label}: ${url} — недоступен (502 Bad Gateway)"
fi
}
show_upstream_health() {
load_env
[[ "$(env_get NGINX_MODE docker)" != "host" ]] && return 0
[[ "$(env_get INSTALL_MODE local)" == "local" ]] && return 0
[[ -n "$(env_get DOMAIN_API "")" ]] || return 0
echo " Upstream (host Nginx → localhost):"
check_local_upstream "API" "http://127.0.0.1:3000/api"
check_local_upstream "Frontend" "http://127.0.0.1:3002"
check_local_upstream "Docs" "http://127.0.0.1:3003/docs"
echo ""
}
show_status() { show_status() {
load_env load_env
echo "" echo ""
@@ -1533,7 +1774,20 @@ show_status() {
echo "" echo ""
docker_cmd compose ps 2>/dev/null || warn "Контейнеры не запущены" docker_cmd compose ps 2>/dev/null || warn "Контейнеры не запущены"
echo "" echo ""
if has_cmd nginx && [[ "$(env_get USE_NGINX_SSL false)" == "true" ]]; then 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"
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"
fi
echo ""
show_upstream_health
if has_cmd nginx && [[ "$(env_get NGINX_MODE docker)" == "host" ]]; then
run_root nginx -t 2>&1 | sed 's/^/ /' run_root nginx -t 2>&1 | sed 's/^/ /'
fi fi
} }
@@ -1594,14 +1848,42 @@ action_renew_ssl() {
esac esac
} }
action_fix_host_proxy() {
[[ -f .env ]] || fail "Файл .env не найден — сначала выполните ./install.sh --install"
load_env
NGINX_MODE="host"
env_set NGINX_MODE "host"
NON_INTERACTIVE=1
log "Исправление прокси: системный Nginx + проброс портов на 127.0.0.1..."
stop_docker_nginx
prepare_compose_stack
refresh_host_nginx_configs
local compose_cmd=(compose --env-file .env)
docker_cmd "${compose_cmd[@]}" up -d --force-recreate "${HOST_EDGE_SERVICES[@]}"
ensure_host_upstreams
if system_nginx_is_active; then
run_root nginx -t
run_root systemctl reload nginx
fi
ok "Прокси исправлен — проверьте: curl -I http://127.0.0.1:3002"
show_status
}
action_restart() { action_restart() {
load_env load_env
write_compose_override prepare_compose_stack
refresh_host_nginx_configs
local compose_cmd=(compose --env-file .env) local compose_cmd=(compose --env-file .env)
if [[ -n "$(env_get DOMAIN_API "")" && "$(env_get INSTALL_MODE local)" != "local" ]]; then if compose_uses_proxy_profile; then
compose_cmd+=(--profile proxy) compose_cmd+=(--profile proxy)
fi fi
docker_cmd "${compose_cmd[@]}" up -d --build docker_cmd "${compose_cmd[@]}" up -d --build
recreate_host_port_services
ensure_host_upstreams
ok "Контейнеры перезапущены" ok "Контейнеры перезапущены"
show_status show_status
} }
@@ -1654,6 +1936,7 @@ main() {
configure-domains) action_configure_domains ;; configure-domains) action_configure_domains ;;
renew-ssl) action_renew_ssl ;; renew-ssl) action_renew_ssl ;;
restart) action_restart ;; restart) action_restart ;;
fix-proxy) action_fix_host_proxy ;;
status) show_status ;; status) show_status ;;
reset-db) action_reset_db ;; reset-db) action_reset_db ;;
remove-nginx) remove_nginx_configs ;; remove-nginx) remove_nginx_configs ;;