From f52e035d8af1eadfce8ada5049bc8f643f792ce2 Mon Sep 17 00:00:00 2001 From: Den Piligrim <89912505+vasiljevdenis@users.noreply.github.com> Date: Mon, 8 Jun 2026 22:47:25 +0300 Subject: [PATCH 1/2] fix: insecure hy2 --- server/src/inbounds/inbound-builder.service.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/server/src/inbounds/inbound-builder.service.ts b/server/src/inbounds/inbound-builder.service.ts index 5a80219..a6650c7 100644 --- a/server/src/inbounds/inbound-builder.service.ts +++ b/server/src/inbounds/inbound-builder.service.ts @@ -469,7 +469,6 @@ export class InboundBuilderService { content: '', dir: '', headers: {}, - insecure: true, rewriteHost: false, statusCode: 0, type: 'proxy', @@ -703,7 +702,6 @@ export class InboundBuilderService { const auth = settings.clients?.[0]?.auth || settings.clients?.[0]?.password || password; const finalmask = stream.finalmask?.udp?.[0]; const params = new URLSearchParams(); - params.set('insecure', '1'); params.set('security', 'tls'); params.set('fp', 'chrome'); params.set('alpn', 'h3'); @@ -769,7 +767,6 @@ export class InboundBuilderService { } const params = new URLSearchParams(); - params.set('insecure', '1'); params.set('security', 'tls'); params.set('fp', 'chrome'); params.set('alpn', 'h3'); From 009506f9151d2c64ca0c1c4055515db6e5485151 Mon Sep 17 00:00:00 2001 From: Den Piligrim <89912505+vasiljevdenis@users.noreply.github.com> Date: Mon, 8 Jun 2026 23:31:17 +0300 Subject: [PATCH 2/2] fix: bd sync --- .gitignore | 1 + docker-compose.yml | 2 + install.sh | 4 + server/src/app.module.ts | 11 ++- .../1770000000001-add-node-domain.ts | 18 +++++ update.sh | 76 +++++++++++++++++-- 6 files changed, 106 insertions(+), 6 deletions(-) create mode 100644 server/src/migrations/1770000000001-add-node-domain.ts diff --git a/.gitignore b/.gitignore index 0686b91..6d9142c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ checker/ client/.env client/coverage/ +backups/ diff --git a/docker-compose.yml b/docker-compose.yml index 41513ba..eed9aea 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -26,6 +26,8 @@ services: DB_USERNAME: ${POSTGRES_USER} DB_PASSWORD: ${POSTGRES_PASSWORD} DB_NAME: ${POSTGRES_DB} + DB_SYNCHRONIZE: "true" + DB_MIGRATIONS_RUN: "false" JWT_SECRET: ${JWT_SECRET} ADMIN_LOGIN: ${ADMIN_LOGIN} ADMIN_PASSWORD: ${ADMIN_PASSWORD} diff --git a/install.sh b/install.sh index 89719c5..0c51db8 100644 --- a/install.sh +++ b/install.sh @@ -469,6 +469,8 @@ services: DB_USERNAME: admin DB_PASSWORD: ${DB_PASS} DB_NAME: 3dp_manager + DB_SYNCHRONIZE: "true" + DB_MIGRATIONS_RUN: "false" JWT_SECRET: ${JWT_SECRET} ADMIN_LOGIN: ${ADMIN_USER} ADMIN_PASSWORD: ${ADMIN_PASS} @@ -580,6 +582,8 @@ services: DB_USERNAME: admin DB_PASSWORD: ${DB_PASS} DB_NAME: 3dp_manager + DB_SYNCHRONIZE: "true" + DB_MIGRATIONS_RUN: "false" JWT_SECRET: ${JWT_SECRET} ADMIN_LOGIN: ${ADMIN_USER} ADMIN_PASSWORD: ${ADMIN_PASS} diff --git a/server/src/app.module.ts b/server/src/app.module.ts index 08e8eba..d748d49 100644 --- a/server/src/app.module.ts +++ b/server/src/app.module.ts @@ -24,6 +24,9 @@ import { Tunnel } from './tunnels/entities/tunnel.entity'; import { SessionModule } from './session/session.module'; import { Node } from './nodes/entities/node.entity'; import { NodesModule } from './nodes/nodes.module'; +import { AddNodesAndNodeRelations1765960000000 } from './migrations/1765960000000-add-nodes-and-node-relations'; +import { AddNodeIpFlagAndInboundLabels1770000000000 } from './migrations/1770000000000-add-node-ip-flag-and-inbound-labels'; +import { AddNodeDomain1770000000001 } from './migrations/1770000000001-add-node-domain'; @Module({ imports: [ @@ -44,7 +47,13 @@ import { NodesModule } from './nodes/nodes.module'; password: process.env.DB_PASSWORD, database: process.env.DB_NAME, entities: [Setting, Domain, Subscription, Inbound, Tunnel, Node], - synchronize: true, + migrations: [ + AddNodesAndNodeRelations1765960000000, + AddNodeIpFlagAndInboundLabels1770000000000, + AddNodeDomain1770000000001, + ], + synchronize: process.env.DB_SYNCHRONIZE !== 'false', + migrationsRun: process.env.DB_MIGRATIONS_RUN === 'true', }), SessionModule, XuiModule, diff --git a/server/src/migrations/1770000000001-add-node-domain.ts b/server/src/migrations/1770000000001-add-node-domain.ts new file mode 100644 index 0000000..7bd4ccd --- /dev/null +++ b/server/src/migrations/1770000000001-add-node-domain.ts @@ -0,0 +1,18 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddNodeDomain1770000000001 implements MigrationInterface { + name = 'AddNodeDomain1770000000001'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + ALTER TABLE "node" + ADD COLUMN IF NOT EXISTS "domain" character varying + `); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "node" DROP COLUMN IF EXISTS "domain"`, + ); + } +} diff --git a/update.sh b/update.sh index 889a23a..ab354b7 100644 --- a/update.sh +++ b/update.sh @@ -38,9 +38,8 @@ check_containers_running() { # Формат: NAME\tSTATUS (например: "3dp-postgres\tUp 2 days" или "3dp-postgres\tError") while IFS=$'\t' read -r container_name status; do if [ -n "$container_name" ] && [ -n "$status" ]; then - # Проверяем, что статус содержит Up/running/healthy/restarting - # Up, Up 2 days, Up Less than a second, (healthy), running, restarting - if ! echo "$status" | grep -qiE "^up|running|healthy|restarting"; then + # Restarting означает, что контейнер не смог стабильно запуститься. + if ! echo "$status" | grep -qiE "^up|running|healthy"; then failed=1 warn "Контейнер $container_name в статусе: $status" fi @@ -284,6 +283,52 @@ remove_hysteria_mount() { mv "$tmp_file" "$compose_file" } +ensure_safe_database_mode() { + local compose_file="$1" + [[ -f "$compose_file" ]] || return 0 + + local tmp_file + tmp_file="$(mktemp)" + + awk ' + /^[[:space:]]+DB_SYNCHRONIZE:/ { next } + /^[[:space:]]+DB_MIGRATIONS_RUN:/ { next } + { + print $0 + if ($0 ~ /^[[:space:]]+DB_NAME:/) { + match($0, /^[[:space:]]+/) + indent = substr($0, RSTART, RLENGTH) + print indent "DB_SYNCHRONIZE: \"false\"" + print indent "DB_MIGRATIONS_RUN: \"true\"" + } + } + ' "$compose_file" > "$tmp_file" + + mv "$tmp_file" "$compose_file" +} + +get_node_count() { + docker exec 3dp-postgres sh -c ' + psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Atqc " + SELECT CASE + WHEN to_regclass('\''public.node'\'') IS NULL THEN 0 + ELSE (SELECT count(*) FROM node) + END + " + ' 2>/dev/null | tr -d '[:space:]' +} + +backup_database() { + local backup_dir="$PROJECT_DIR/backups" + BACKUP_FILE="$backup_dir/pre-update-$(date +%Y%m%d-%H%M%S).sql.gz" + + mkdir -p "$backup_dir" + log "Создание резервной копии базы данных: $BACKUP_FILE" + docker exec 3dp-postgres sh -c \ + 'pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB"' | gzip > "$BACKUP_FILE" + chmod 600 "$BACKUP_FILE" +} + need_root() { [[ $EUID -eq 0 ]] || die "Запускать только от root" } @@ -314,7 +359,11 @@ log "Compose команда: ${COMPOSE_CMD[*]}" ################################# # CHECK AND FIX CREDENTIALS ################################# -check_and_fix_credentials || true +# Обновление не должно менять пароль уже инициализированной PostgreSQL: +# изменение только .env делает существующую базу недоступной. +if [[ ! -f ".env" ]]; then + die "Файл .env не найден. Обновление остановлено, чтобы не потерять доступ к существующей базе данных" +fi ################################# # FIX NGINX CONFIG @@ -322,6 +371,16 @@ check_and_fix_credentials || true ensure_nginx_api_timeouts "$PROJECT_DIR/client/nginx-client.conf" ensure_bus_location "$PROJECT_DIR/client/nginx-client.conf" remove_hysteria_mount "$PROJECT_DIR/docker-compose.yml" +ensure_safe_database_mode "$PROJECT_DIR/docker-compose.yml" + +################################# +# BACKUP DATABASE +################################# +node_count_before="$(get_node_count)" +[[ "$node_count_before" =~ ^[0-9]+$ ]] || die "Не удалось проверить количество нод перед обновлением" +backup_database +backup_file="$BACKUP_FILE" +[[ -s "$backup_file" ]] || die "Не удалось создать резервную копию базы данных" ################################# # REBUILD BACKEND @@ -341,11 +400,18 @@ log "Пересоздание контейнеров..." # Проверка: все ли контейнеры запустились if ! check_containers_running 60; then - error "Не удалось запустить контейнеры. Логи:" + warn "Не удалось запустить контейнеры. Логи:" "${COMPOSE_CMD[@]}" logs --tail=50 die "Обновление прервано из-за ошибки запуска контейнеров" fi +node_count_after="$(get_node_count)" +[[ "$node_count_after" =~ ^[0-9]+$ ]] || die "Не удалось проверить количество нод после обновления. Резервная копия: $backup_file" +if (( node_count_after < node_count_before )); then + "${COMPOSE_CMD[@]}" stop backend || true + die "Количество нод уменьшилось с $node_count_before до $node_count_after. Обновление остановлено, резервная копия: $backup_file" +fi + log "Очистка старых Docker-образов (освобождение места)..." docker image prune -f