From fb68047c029953896bd022504320e4978ff8044c Mon Sep 17 00:00:00 2001 From: Ivan Razin Date: Mon, 6 Jul 2026 09:55:57 +0300 Subject: [PATCH] Fix diag 404: derive panel domain from webCertFile, purge stale vhosts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The diagnostics page 404'd because the fresh panel vhost (with the diag SSO bridge) was written to the wrong filename and never served: the nginx-scan domain detection picked the wrong panel domain when stale / duplicate vhost files from older installs lingered (the loop result is glob/locale-order dependent, and a leftover panel vhost shadowed the real one by server_name). The vhost that actually served traffic was a stale, pre-bridge config, so //diag fell through to a 404. - Panel domain now comes from the authoritative source, the cert x-ui is configured with (DB webCertFile -> /root/cert// or /etc/letsencrypt/live//); nginx scan is only a fallback, and it no longer overwrites an already-resolved domain. - Skip 00-maps.conf in the detection loop. - At activation: remove stale panel/reality vhost FILES whose name doesn't match the managed domains, wipe ALL sites-enabled symlinks, then relink only the four managed configs — so nothing stale can stay loaded and shadow the panel vhost. Co-Authored-By: Claude Opus 4.8 --- x-ui-patch.sh | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/x-ui-patch.sh b/x-ui-patch.sh index e7c0283..a7e3277 100644 --- a/x-ui-patch.sh +++ b/x-ui-patch.sh @@ -51,22 +51,32 @@ printf " sub_port = %-6s sub_path = %s\n" "$sub_port" "$sub_path" printf " panel_port = %-6s panel_path = %s\n" "$panel_port" "$panel_path" printf " json_path = %s\n" "$json_path" -# ── detect domains from existing nginx ─────────────────────────────────────── -blue "Detecting domains from nginx configs..." +# ── detect domains ──────────────────────────────────────────────────────────── +blue "Detecting domains..." domain="" reality_domain="" +# Panel domain: authoritative source is the cert x-ui is configured with +# (/root/cert//...). Scanning nginx alone is unreliable — stale/duplicate +# vhost files from older installs shadow each other and the loop's result becomes +# glob/locale-order dependent, which is how the panel vhost ended up written to +# the wrong filename (bridge missing on the file that actually serves traffic). +web_cert=$(db "SELECT value FROM settings WHERE key='webCertFile';") +if [[ "$web_cert" =~ ^/root/cert/([^/]+)/ || "$web_cert" =~ /etc/letsencrypt/live/([^/]+)/ ]]; then + domain="${BASH_REMATCH[1]}" +fi + for f in /etc/nginx/sites-available/*; do [[ -f "$f" ]] || continue - [[ "$(basename "$f")" == "80.conf" ]] && continue + case "$(basename "$f")" in 80.conf|00-maps.conf) continue;; esac if grep -q 'listen 7443' "$f" 2>/dev/null; then - domain=$(awk '/server_name/{print $2; exit}' "$f" | tr -d ';') + [[ -z "$domain" ]] && domain=$(awk '/server_name/{print $2; exit}' "$f" | tr -d ';') elif grep -q 'listen 9443' "$f" 2>/dev/null; then reality_domain=$(awk '/server_name/{print $2; exit}' "$f" | tr -d ';') fi done -[[ -n "$domain" ]] || die "Could not find panel domain (nginx config with 'listen 7443')" +[[ -n "$domain" ]] || die "Could not determine panel domain (no webCertFile, no vhost with 'listen 7443')" [[ -n "$reality_domain" ]] || die "Could not find reality domain (nginx config with 'listen 9443')" printf " domain = %s\n" "$domain" printf " reality_domain = %s\n" "$reality_domain" @@ -570,7 +580,22 @@ server { EOF # ── activate sites ──────────────────────────────────────────────────────────── -rm -f /etc/nginx/sites-enabled/default /etc/nginx/sites-available/default +# Drop stale panel/reality vhost FILES whose name doesn't match the domains we +# manage (leftovers from older installs). If left, they shadow the fresh vhosts +# by server_name and mislead the detection fallback above. +for f in /etc/nginx/sites-available/*; do + [[ -f "$f" ]] || continue + bn=$(basename "$f") + case "$bn" in 80.conf|00-maps.conf|"$domain"|"$reality_domain") continue;; esac + if grep -qE 'listen (7443|9443)' "$f" 2>/dev/null; then + blue "Removing stale vhost: $bn" + rm -f "$f" + fi +done +# Wipe every enabled symlink and relink only what we manage, so nothing stale can +# stay loaded and shadow the panel vhost (this was the cause of the diag 404). +find /etc/nginx/sites-enabled -mindepth 1 -delete 2>/dev/null || true +rm -f /etc/nginx/sites-available/default ln -sf "/etc/nginx/sites-available/00-maps.conf" /etc/nginx/sites-enabled/ ln -sf "/etc/nginx/sites-available/${domain}" /etc/nginx/sites-enabled/ ln -sf "/etc/nginx/sites-available/${reality_domain}" /etc/nginx/sites-enabled/